Ruby 如何检查文件是否仍被当前线程锁定?
以下是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 在多线程环境中,当许多线程试图锁定文件并随后将其删除时,一个
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()之后
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