python 的 fcntl.flock 函数是否提供文件访问的线程级锁定?

Boa*_*oaz 2 python linux multithreading locking flock

Python 的 fcnt 模块提供了一个名为 [flock][1] 的方法来证明文件锁定。它的描述是这样的:

对文件描述符 fd 执行锁定操作 op(也接受提供 fileno() 方法的文件对象)。有关详细信息,请参阅 Unix 手册 flock(2)。(在某些系统上,使用 fcntl() 模拟此函数。)

查找flock的linux man page,只提到了跨进程锁定,例如:

如果另一个进程持有不兼容的锁,则对 flock() 的调用可能会阻塞。要发出非阻塞请求,请在上述任何操作中包含 LOCK_NB(通过 ORing)。

所以我的问题是: flock() 是否也提供线程安全锁定并锁定同一进程内的多个线程以及来自不同进程的线程?

[1]:http ://docs.python.org/library/fcntl.html#fcntl.flockfunction 使用 fcntl() 模拟

Gle*_*ard 5

flock锁不关心线程——事实上,它们也不关心进程。如果您在两个进程中使用相同的文件描述符(通过 fork 继承),则使用该 FD 锁定文件的任一进程都将获得两个进程的锁。换句话说,在下面的代码中,两个 flock调用都将返回成功:子进程锁定文件,然后父进程获取相同的锁而不是阻塞,因为它们都是同一个 FD。

import fcntl, time, os

f = open("testfile", "w+")
print "Locking..."
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
print "locked"
fcntl.flock(f.fileno(), fcntl.LOCK_UN)

if os.fork() == 0:
    # We're in the child process, and we have an inherited copy of the fd.
    # Lock the file.
    print "Child process locking..."
    fcntl.flock(f.fileno(), fcntl.LOCK_EX)
    print "Child process locked..."
    time.sleep(1000)
else:
    # We're in the parent.  Give the child process a moment to lock the file.
    time.sleep(0.5)

    print "Parent process locking..."
    fcntl.flock(f.fileno(), fcntl.LOCK_EX)
    print "Parent process locked"
    time.sleep(1000)
Run Code Online (Sandbox Code Playgroud)

同样,如果您锁定同一个文件两次,但使用不同的文件描述符,则这些锁将相互阻塞——无论您是在同一个进程中还是在同一个线程中。见羊群(2):If a process uses open(2) (or similar) to obtain more than one descriptor for the same file, these descriptors are treated independently by flock(). An attempt to lock the file using one of these file descriptors may be denied by a lock that the calling process has already placed via another descriptor.

记住对于 Linux 内核来说,进程和线程本质上是一回事是很有用的,并且内核级 API 通常对它们进行相同的处理。在大多数情况下,如果系统调用记录进程间子/父行为,线程也会如此。

当然,您可以(并且可能应该)自己测试这种行为。

  • 您是在以一种迂回的方式说要正确使用锁,您需要在每个上下文中获得不同的文件描述符吗? (4认同)