gpt4 book ai didi

ruby - 如何使用 File#flock 对独占锁发出非阻塞请求?

转载 作者:数据小太阳 更新时间:2023-10-29 06:43:36 26 4
gpt4 key购买 nike

我应该如何请求非阻塞锁?

为什么 Ruby 没有 File#flock单独尝试锁定文件时是否按预期工作?将文件锁定在一个 block 中并不是此问题的正确解决方案,因为重点是显示锁定持久 锁的行为。在 block 内使用 File#flock 会在 block 退出时释放锁,因此它无法正确显示问题。

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::EINVALErrno::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

首选原生文件#flock解决方案

虽然人们可能会使用 Timeout module在无法获得独占锁时引发 Timeout::Error,似乎 File#flock 应该能够在 native 解决此问题。那么,实际上应该如何在不阻塞的情况下请求独占锁呢?

最佳答案

使用带独占锁的超时模块

您可以使用 Timeout module设置#flock 获取独占锁的持续时间。以下示例将引发 Timeout::Error: execution expired,然后可以以适合应用程序的任何方式挽救。当计时器到期时返回 nil 允许测试 #flock 表达式的真实性。

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

对非阻塞锁尝试使用按位或

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运算符,而不是逻辑或关键字作为 defined in parse.y通过 tOROP 解析器 token 。因此,当独占锁失败时允许#flock 返回false 的正确参数实际上是File::LOCK_NB|File::LOCK_EX。例如:

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

这将在可用时始终生成排他锁;否则,它会立即返回一个假值,而不会产生引发或拯救异常的开销。这显然是该模块的预期使用方式,但文档可以使用一些说明和其他示例来使其更易于理解。

关于ruby - 如何使用 File#flock 对独占锁发出非阻塞请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15304833/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com