• fcntl:文件的加锁与解锁


    当我们在读写文件的时候,如果多个进程同时进行操作的话,那么很容易出现混乱。这时候就需要加锁了,正如操作数据库表的时候需要加锁一样。

    而 Python 提供了一个库:fcntl,通过 fcntl.flock 函数即可实现对文件进行加锁和解锁。

    注意:这个模块目前不支持 Windows,我们只能在类 Unix 下使用。

    fcntl.flock 接收两个参数,第一个参数是文件描述符,第二个参数是 operation。常见的 operation 如下:

    • fcntl.LOCK_SH: 共享锁, 所有进程对当前文件都没有写权限, 即使加锁的进程也没有, 但是都具有读权限;
    • fcntl.LOCK_EX: 排它锁, 除了加锁进程具有当前文件的读写权限之外, 其它的进程都没有;
    • fcntl.LOCK_UN: 对加锁文件进行解锁;
    • fcntl.LOCK_MAND: 共享模式强制锁, 可以和 LOCK_READ 或者 LOCK_WRITE 联合起来使用, 从而表示是否允许并发的读操作或者并发的写操作(基本不用);
    • fcntl.LOCK_NB: 非阻塞锁, 如果指定此参数, 函数不能获得文件锁就立即返回; 否则, 函数会等待获得文件锁, LOCK_NB 可以同 LOCK_SH、LOCK_EX 进行按位或操作;

    例如:如果一个文件设置了排它锁,fcntl.flock(f.fileno(), fcntl.LOCK_EX),那么当其它进程在请求获取这个锁的时候就会一直阻塞在这里。

    但如果是 fcntl.flock(f.fileno(), fcntl.LOCK_EX | fnctl.LOCK_NB),那么其它进程在获取不到锁的时候就直接返回了。

    需要注意的是,在给文件加锁之前,一定要保证文件以相应的访问模式打开。

    比如共享锁是让所有进程对文件只有读权限,那么在加共享锁的时候要保证文件以读方式打开;加上排它锁的时候,文件要以可写的形式打开。

    下面举例说明,由于 fcntl 不支持 Windows,我就在我阿里云上的 CentOS 上演示了。

    这里我们打开一个终端,以可读可写模式打开 1.sh 这个文件,然后加上排它锁。接下来我们再打开一个终端,再次对这个文件进行加锁。

    但是问题来了,我们发现阻塞在这里了,因为这个文件已经被加锁了。所以我们回到之前的终端,将锁给释放掉。

    再来看看第二个终端。

    此时已经不再阻塞了,因为第一个终端把锁解除了。

    当然我们说设置了排它锁的话,其它进程在获取不到锁的时候会阻塞,但排它锁如果和 fcntl.LOCK_NB 结合使用的话,在获取不到锁的时候会直接返回。

    现在锁已经被第二个终端获取,我们在第一个终端继续尝试获取锁。

    # 依旧会阻塞在这里
    >>> fcntl.flock(f.fileno(), fcntl.LOCK_EX)
    ^CTraceback (most recent call last):
      File "<stdin>", line 1, in <module>
    KeyboardInterrupt
    
    # 如果和 fcntl.LOCK_NB 结合的话, 那么在获取不到锁的时候会立即返回
    # 只不过是以报错的形式, 提示: 资源暂时不可用
    >>> fcntl.flock(f.fileno(), fcntl.LOCK_EX|fcntl.LOCK_NB)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    BlockingIOError: [Errno 11] Resource temporarily unavailable
    >>> 
    
  • 相关阅读:
    590. N-ary Tree Postorder Traversal
    700. Search in a Binary Search Tree
    885. Spiral Matrix III
    876. Middle of the Linked List
    908. Smallest Range I
    java中Class对象详解和类名.class, class.forName(), getClass()区别
    应用层之web和http
    122. 买卖股票的最佳时机 II
    129. 求根到叶子节点数字之和
    849. 到最近的人的最大距离
  • 原文地址:https://www.cnblogs.com/traditional/p/9218885.html
Copyright © 2020-2023  润新知