ruby – 如何使用File#flock对独占锁进行非阻塞请求?

前端之家收集整理的这篇文章主要介绍了ruby – 如何使用File#flock对独占锁进行非阻塞请求?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我应该如何请求非阻塞锁?

为什么Ruby 7 File#flock在单独尝试锁定文件时工作正常?将文件锁定在块中不是解决此问题的正确解决方案,因为重点是显示锁定持久锁的行为.在块中使用File#flock释放锁,当该块退出时,它不会正确显示问题.

File#flock以各种方式失败,特别是在请求非阻塞锁时.一些例子如下.

失败的文件#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',0644)
f2.flock(File::LOCK_EX)

>当文件被专门锁定时,请求非阻塞锁导致无效的参数异常.

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

f2 = File.open('foo',0644)
f2.flock(File::LOCK_NB)
# => Errno::EINVAL: Invalid argument - foo

>文档说#flock“根据locked_constant锁定或解锁文件(逻辑或下表中的值)”.但是,逻辑OR会根据平台引发Errno :: EINVAL或Errno :: EBADF.

f1 = File.open('foo',0644)
f2.flock(File::LOCK_NB || File::LOCK_EX)
# => Errno::EINVAL: Invalid argument - foo

本机文件#flock解决方案首选

虽然可能使用Timeout module来提高超时::错误时无法获得排他锁,似乎File#flock应该能够本来解决这个问题.那么,一个实际上应该如何请求一个排他锁呢?

解决方法

使用具有独占锁的超时模块

您可以使用Timeout module设置#flock的持续时间来获取排他锁.以下示例将引发超时::错误:执行过期,然后可以以适用于应用程序的任何方式进行抢救.当定时器到期时返回零,允许#flock表达式被测试为真值.

require 'timeout'

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

使用按位或进行非阻塞锁定尝试

File#flock的文档说:

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.

然而,该方法实际上期望一个Bitwise OR运算符,而不是逻辑OR关键字为defined in parse.y由tOROP解析器令牌.结果,允许#flock在排除锁定失败时返回false的正确参数实际上是File :: LOCK_NB | File :: LOCK_EX.例如:

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

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

f1.close; f2.close
# => nil

这可以一直生成排他锁;否则,它立即返回一个伪造值,而不会引发或拯救异常.这显然是模块的使用方式,但文档可以使用一些澄清和其他示例来使其更容易理解.

猜你在找的Ruby相关文章