您基本上已经开发了二进制信号量(或互斥体)的文件系统版本。这是一个经过充分研究的用于锁定的结构,因此只要您正确理解实现细节,它就应该可以工作。诀窍是让“测试和设置”操作,或者在您的情况下“检查存在并移动”,成为真正的原子操作。为此,我会使用这样的东西:
lock_acquired = False
while not lock_acquired:
try:
move(fh, fhtemp)
except:
sleep(3)
else:
lock_acquired = True
# do your writing
move(fhtemp, fh)
lock_acquired = False
您拥有的程序在大多数情况下都可以工作,但正如前面提到的,如果另一个进程在检查文件是否存在和调用之间移动文件,您可能会遇到问题move
。我想你可以解决这个问题,但我个人建议坚持使用经过充分测试的互斥算法。 (我已经翻译/移植了上面的代码示例现代操作系统作者:Andrew Tanenbaum,但我可能在转换中引入了错误 - 只是公平的警告)
顺便说一下,手册页open
Linux 上的函数提供了文件锁定的解决方案:
使用锁文件执行原子文件锁定的解决方案是在同一文件系统上创建一个唯一的文件(例如,合并主机名和 pid),使用 link(2) 建立到锁文件的链接。如果link()返回0,则锁定成功。否则,对唯一文件使用 stat(2) 检查其链接计数是否已增加到 2,在这种情况下锁定也成功。
要在 Python 中实现它,您可以执行以下操作:
# each instance of the process should have a different filename here
process_lockfile = '/path/to/hostname.pid.lock'
# all processes should have the same filename here
global_lockfile = '/path/to/lockfile'
# create the file if necessary (only once, at the beginning of each process)
with open(process_lockfile, 'w') as f:
f.write('\n') # or maybe write the hostname and pid
# now, each time you have to lock the file:
lock_acquired = False
while not lock_acquired:
try:
link(process_lockfile, global_lockfile)
except:
lock_acquired = (stat(process_lockfile).st_nlinks == 2)
else:
lock_acquired = True
# do your writing
unlink(global_lockfile)
lock_acquired = False