我应该如何申请非阻塞锁?
当单独尝试锁定文件时,为什么 Ruby 的File#flock不能按预期工作?将文件锁定在块中并不是解决此问题的正确解决方案,因为重点是显示锁定持久锁的行为。在块内使用 File#flock 会在块退出时释放锁,因此它不能正确演示问题。
File#flock 以多种方式失败,尤其是在请求非阻塞锁时。下面是一些例子。
File#flock 的失败示例
使用多个独占锁时无限等待,因为#flock 不提供超时锁请求的方法。
# First lock succeeds. f1 = File.open('foo', File::RDWR|File::CREAT, 0644) f1.flock(File::LOCK_EX) # => 0 # This never returns. f2 = File.open('foo', File::RDWR|File::CREAT, 0644) f2.flock(File::LOCK_EX)
在文件被独占锁定时请求非阻塞锁定会导致无效参数异常。
f1 = File.open('foo', File::RDWR|File::CREAT, 0644) f1.flock(File::LOCK_EX) # => 0 f2 = File.open('foo', File::RDWR|File::CREAT, 0644) f2.flock(File::LOCK_NB) # => Errno::EINVAL: Invalid argument - foo
文档说#flock“根据locking_constant(下表中的逻辑或值)锁定或解锁文件。” 但是,逻辑或会引发
Errno::EINVAL
或Errno::EBADF
取决于平台。f1 = File.open('foo', File::RDWR|File::CREAT, 0644) f1.flock(File::LOCK_EX) # => 0 f2 = File.open('foo', File::RDWR|File::CREAT, 0644) f2.flock(File::LOCK_NB || File::LOCK_EX) # => Errno::EINVAL: Invalid argument - foo
Native File#flock 解决方案首选
虽然在无法获得独占锁时可能会使用Timeout 模块来引发Timeout::Error
,但似乎 File#flock 应该能够本机解决这个问题。那么,实际上应该如何在不阻塞的情况下请求独占锁呢?