最近工作当中做了一个项目,这个项目主要是操作文件的。
在操作耗时操作的时候,我们一般采用多线程或者多进程。在开发中,如果多个线程需要对文件进行读写操作,就需要用到线程锁或者是文件锁。
使用fcntl
在Linux下,Python的标准库有线程的文件锁,来自fcntl模块。这个模块提供了Unix系统fcntl()和ioctl()的接口。
对于文件锁的操作,主要需要使用fcntl.flock(fd,operation)这个函数。
其中,参数fd表示文件描述符;参数operation指定要进行的锁操作,该参数的取值有如下几种:
- LOCK_SH:表示要穿件一个共享锁,在任意时间内,一个文件的共享锁可以被多个进程拥有。
- LOCK_EX:表示创建一个排它锁,在任意时间内,一个文件的排它锁只能被一个进程拥有
- LOCK_UN:表示删除该进程创建的锁
- LOCK_MAND:它主要是用于共享模式强制锁,它可以与LOCK_READ或者LOCK_WRITE联合起来使用,从而表示是否允许并发的读操作或者并发的写操作。
我这次工作的应用场景是两个py文件操作同一个文本,所以是多进程操作文本。
#!/usr/bin/python
# coding:utf-8
import fcntl
import threading
import time
def writetoTxt():
id = threading.currentThread().getName()
with open("aaa.txt", "a") as f:
# fcntl.flock(f.fileno(), fcntl.LOCK_EX) # 加锁
print("{} acquire lock".format(id))
for i in range(10):
f.write('"write from" + str(i) + {} \n'.format(id))
time.sleep(2)
# 在with块外,文件关闭,自动解锁
print("{} exit".format(id))
if __name__ == '__main__':
writetoTxt()
执行结果:
使用文件锁
没有使用文件锁
如果从执行结果出发,我们看不出两者之间的区别,我想应该是写入内容太少了,看不出效果,有时间再研究下。
通过执行界面,我们是可以看出两者的区别的:
使用文件锁
从下面两个图中,我们可以看出,file_lock1.py文件是处于阻塞状态的,但是没有退出。
不使用文件锁
说明这两个进程都不会被阻塞。
注意:
1、文件close之火,文件锁也会失效
2、进程结束后,文件锁也会失效
3、flock()的LOCK_EX是"劝告锁",系统内核不会强制检查锁的状态,需要在代码中进行文件操作的地方显示检查才能生效。
相关资料:
1.Linux中的文件锁的概念及其实现(http://blog.csdn.net/jianhong1990/article/details/26369465)
2.fcntl模块的官方文档(https://docs.python.org/2/library/fcntl.html#fcntl.flock)
建议:
没事还是多看看官方文档吧,能收获很多。