Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何检查文件是否仍被当前线程锁定?_Ruby_Multithreading - Fatal编程技术网

Ruby 如何检查文件是否仍被当前线程锁定?

Ruby 如何检查文件是否仍被当前线程锁定?,ruby,multithreading,Ruby,Multithreading,以下是Ruby代码: File.open('a.txt', File::CREAT | File::RDWR) do |f| # Another thread deletes the a.txt file here f.flock(File::LOCK_EX | File::LOCK_NB) # How do I check that the file is really locked by my thread? end 在多线程环境中,当许多线程试图锁定文件并随后将其删除时,一个

以下是Ruby代码:

File.open('a.txt', File::CREAT | File::RDWR) do |f|
  # Another thread deletes the a.txt file here
  f.flock(File::LOCK_EX | File::LOCK_NB)
  # How do I check that the file is really locked by my thread?
end
在多线程环境中,当许多线程试图锁定文件并随后将其删除时,一个线程可能会在调用
flock()
之前将其删除。在这种情况下,
flock()
仍然认为文件已就位并返回
true

我正试图找到一种方法,在
flock()
完成后,检查文件是否真的被当前线程锁定。我该怎么做?

如果
f.flock(File::LOCK_EX | File::LOCK_NB)
返回非
false
值,则
f
被锁定。它将保持锁定,直到您关闭文件或显式调用
f.flock(file::lock\u UN)
。您不必检查它是否再次锁定。为了解释实际发生的情况,我们需要首先研究文件系统内部和相关的系统调用:

 File Descriptor Table       Open File Table        i-node Table      Directory Index
╒════════════════════╕       ╒═════════════╕       ╒════════════╕     ╒═════════════╕
┃3 ..................┣━━━━━━▷┃ open file1  ┣━━┳━━━▷┃ /tmp/file1 ┃◃━━━━┫ file1       ┃
┃4 ..................┣━━━━━━▷┃ open file1  ┣━━┚ ┏━▷┃ /tmp/file2 ┃◃━━━━┫ file2       ┃
┃5 ..................┣━━━┳━━▷┃ open file2  ┣━━━━┚                   
┃6 ..................┣━━━┚
此图中的关键点是i-node表中有两个不同且不相关的入口点:打开文件表和目录索引。不同的系统调用使用不同的入口点:

  • 打开(文件路径)=>从目录索引中查找i节点编号,并在文件描述符表引用的打开文件表中创建一个条目(每个进程一个表),然后在相关i节点表条目中增加ref_计数器
  • 关闭(文件描述符)=>关闭(释放)相关文件描述符表项和打开文件表中的相关项(除非有其他引用文件描述符),然后递减相关i节点表项中的引用计数器(除非打开文件项保持打开)
  • 取消链接(文件路径)=>没有删除系统调用!通过从目录索引中删除条目,取消i节点表与目录索引的链接。递减相关i节点表项中的计数器(不知道打开的文件表!)
  • flock(file_desriptor)=>对打开的文件表中的条目应用/删除锁定(不知道目录索引!)
  • 如果ref_计数器变为零,则删除i节点表项(实际上是删除文件)。它可以发生在close()或unlink()之后
这里的关键点是,取消链接不一定会立即删除文件(数据)!它仅取消目录索引和i节点表的链接。这意味着,即使在取消链接后,文件仍可能被打开,并带有活动锁

记住这一点,设想以下场景,使用2个线程,尝试使用open/flock/close在文件上同步,并尝试使用unlink进行清理:

   THREAD 1                              THREAD 2
==================================================
       |                                    |
       |                                    |
(1) OPEN (file1, CREATE)                    |
       |                             (1) OPEN (file1, CREATE)
       |                                    |
(2) LOCK-EX (FD1->i-node-1)                 |
  [start work]                       (2) LOCK-EX (FD2->i-node-1) <---
       |                                    .                       |
       |                                    .                       |
(3)  work                                   .                       |
       |                             (3) waiting loop               |
       |                                    .                       |
   [end work]                               .                       |
(4) UNLINK (file1)                          . -----------------------
(5) CLOSE (FD1)--------unlocked------> [start work]
       |                                    |
       |                                    |
(6) OPEN (file1, CREATE)                    |
       |                                    |
       |                             (5)  work
(7) LOCK-EX (FD1->i-node-2)                 |
  [start work] !!! does not wait            |
       |                                    |
(8)  work                                   |
       |                                    |
下面是您从问题中重新编写的示例:

FS.instance.open('a.txt') do |f|
  if f.flock(File::LOCK_EX | File::LOCK_NB)
    # you can be sure that you have a lock
  end
  # 'a.txt' will finally be deleted
end

能否将锁定标志传递给
文件。打开
调用?例如,
File.open('a.txt',File::CREAT | File::RDWR | File::LOCK | EX | File::LOCK | NB)
@wizadofogz不是个坏主意,但是你能展示整个代码吗?看起来我的建议不起作用:(可能是重复?
FS.instance.open('a.txt') do |f|
  if f.flock(File::LOCK_EX | File::LOCK_NB)
    # you can be sure that you have a lock
  end
  # 'a.txt' will finally be deleted
end