Python 使用 `with:` 语句的文件锁模块行为

Python filelock module behavior using `with:` statement

我只是想知道 python 模块文件锁的细节及其在某些情况下的行为。

首先,with: 语句究竟是如何被线程处理的。如果多个线程调用 with: 是否会逐个线程锁定?有没有可能两个线程同时获取锁?

其次,当我使用with:时,我必须在使用后清除锁吗? with:语句执行完后锁会自动清除吗?

第三,我的代码中有一个实例,我认为必须创建一个文件然后立即将其锁定。目前我正在使用这个:

channel_file = open(os.path.join('channels', username), 'w+')
with filelock.FileLock(os.path.join('channels', username)):
  channel_file.write(json.dumps({'rate': reobj.group(1),'time': reobj.group(2)}))

如果自文件创建以来另一个线程有可能读取该文件,这是否可以防止这种情况发生?

这也引出了第四点。使用 with: 时文件锁是否锁定读取访问权限?

  1. FileLock 维护一个锁计数器,该计数器在进程中的所有线程之间共享,并受到 thread-wise 锁的保护。每次调用 acquire() 都会增加锁计数器,并且在计数器为零时额外获得 OS-level 文件锁。同样,每次调用 release() 都会减少锁定计数器并在计数器达到零时解锁文件。

    因此,如果两个线程同时获取锁,则文件会在OS级别被本进程锁一次,锁计数器会增加2。两个线程不会互相阻塞。

  2. with:的重点是在其作用域退出后自动获取和释放锁。见 What is the python "with" statement designed for?.

  3. 文件锁用于防止当前进程之外的文件访问。它不用于 thread-wise 锁定。使用常规 threading.Lock 进行 thread-wise 锁定。

    # in __main__ or somewhere before we start the threads.
    channel_lock = threading.Lock()
    
    # in the worker thread
    with channel_lock:
        with open(...) as channel_file:
            channel_file.write(...)
    

有关实施细节,您可以参考 source code of py-filelock