How can I make a non-blocking request for an exclusive lock using File#flock?

你说的曾经没有我的故事 提交于 2019-12-03 02:40:12

Use Timeout Module with Exclusive Locks

You can use the Timeout module to set a duration for #flock to acquire an exclusive lock. The following example will raise Timeout::Error: execution expired, which can then be rescued in whatever way seems appropriate for the application. Returning nil when the timer expires allows the #flock expression to be tested for truth.

require 'timeout'

f1 = File.open('foo', File::RDWR|File::CREAT, 0644)
f1.flock(File::LOCK_EX)
# => 0

f2 = File.open('foo', File::RDWR|File::CREAT, 0644)
Timeout::timeout(0.001) { f2.flock(File::LOCK_EX) } rescue nil
# => nil

Use Bitwise OR for Non-Blocking Lock Attempts

The documentation for File#flock says:

Locks or unlocks a file according to locking_constant (a logical or of the values in the table below). Returns false if File::LOCK_NB is specified and the operation would otherwise have blocked.

However, the method actually expects a Bitwise OR operator, rather than a Logical OR keyword as defined in parse.y by the tOROP parser token. As a result, the correct argument that allows #flock to return false when an exclusive lock fails is actually File::LOCK_NB|File::LOCK_EX. For example:

f1 = File.open('foo', File::RDWR|File::CREAT, 0644)
f1.flock(File::LOCK_EX|File::LOCK_NB)
# => 0

f2 = File.open('foo', File::RDWR|File::CREAT, 0644)
f2.flock(File::LOCK_NB|File::LOCK_EX)
# => false

f1.close; f2.close
# => nil

This will consistently generate an exclusive lock when available; otherwise, it immediately returns a falsy value without the overhead of raising or rescuing exceptions. This is obviously the way the module is intended to be used, but the documentation could use some clarification and additional examples to make it easier to understand.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!