对Python多线程读写文件加锁的实例详解


Posted in Python onJanuary 14, 2019

Python的多线程在io方面比单线程还是有优势,但是在多线程开发时,少不了对文件的读写操作。在管理多个线程对同一文件的读写操作时,就少不了文件锁了。

使用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联合起来使用,从而表示是否允许并发的读操作或者并发的写操作

demo

import fcntl
import threading
import time
 
 
def writetoTxt(txtFile):
 id = threading.currentThread().getName()
 with open(txtFile, 'a') as f:
  fcntl.flock(f.fileno(), fcntl.LOCK_EX) #加锁
  print "{0} acquire lock".format(id)
  f.write("write from {0} \r\n".format(id))
  time.sleep(3)
 # 在with块外,文件关闭,自动解锁
 print "{0} exit".format(id)
 
 
for i in range(5):
 myThread = threading.Thread(target=writetoTxt, args=("test.txt",))
 myThread.start()

代码运行期间,控制台将依次打印哪个线程获得了锁,在对文件进行读写。

Thread-1 acquire lock
Thread-1 exit
Thread-2 acquire lock
Thread-2 exit
Thread-3 acquire lock
Thread-3 exit
Thread-5 acquire lock
Thread-5 exit
Thread-4 acquire lock
Thread-4 exit

小结

通过调用

fcntl.flock(f.fileno(), fcntl.LOCK_EX)

对文件加锁,如果有其他线程尝试对test文件加锁,会被阻塞。

当线程执行完毕的时候,锁会自动释放。或者也可以采取主动的方式解锁:调用

fcntl.flock(f.fileno(),fcntl.LOCK_UN)

函数, 对文件test解锁

使用线程锁

当多个线程共享一个数据的时候,必须要进行同步的控制,不然会出现不可预期的结果,即 “线程不安全”

线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。

互斥锁为资源引入一个状态:锁定/非锁定。

某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;

直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。

互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

threading模块中定义了Lock类,可以方便的处理锁定:

#创建锁
mutex = threading.Lock()
#锁定
mutex.acquire([timeout])
#解锁
mutex.release()

Demo

使用互斥锁实现上面的例子的代码如下:

import threading
import time
 
def writetoTxt(txtFile):
 id = threading.currentThread().getName()
 mutex.acquire(10)
 with open(txtFile, 'a') as f:
  print "Thread {0} acquire lock".format(id)
  f.write("write from thread {0} \r\n".format(id))
  time.sleep(3)
 mutex.release()
 print "Thread {0} exit".format(id)
 
 
mutex = threading.Lock()
 
for i in range(5):
 myThread = threading.Thread(target=writetoTxt, args=("test.txt",))
 myThread.start()

(上述代码本质上是一个顺序执行的单线程)

结果:

Thread Thread-1 acquire lock
Thread Thread-1 exit
Thread Thread-2 acquire lock
Thread Thread-2 exit
Thread Thread-3 acquire lock
Thread Thread-3 exit
Thread Thread-4 acquire lock
Thread Thread-4 exit
Thread Thread-5 acquire lock
Thread Thread-5 exit

小结

当一个线程调用锁的acquire()方法获得锁时,锁就进入“locked”状态。每次只有一个线程可以获得锁。如果此时另一个线程试图获得这个锁,该线程就会变为“blocked”状态,称为“同步阻塞”。

直到拥有锁的线程调用锁的release()方法释放锁之后,锁进入“unlocked”状态。线程调度程序从处于同步阻塞状态的线程中选择一个来获得锁,并使得该线程进入运行(running)状态。

以上这篇对Python多线程读写文件加锁的实例详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python模仿POST提交HTTP数据及使用Cookie值的方法
Nov 10 Python
Python使用SocketServer模块编写基本服务器程序的教程
Jul 12 Python
python paramiko模块学习分享
Aug 23 Python
Python读取Json字典写入Excel表格的方法
Jan 03 Python
numpy 进行数组拼接,分别在行和列上合并的实例
May 08 Python
Python利用splinter实现浏览器自动化操作方法
May 11 Python
使用Python获取网段IP个数以及地址清单的方法
Nov 01 Python
对pandas中iloc,loc取数据差别及按条件取值的方法详解
Nov 06 Python
Python判断有效的数独算法示例
Feb 23 Python
Pytorch 实现权重初始化
Dec 31 Python
Python批量获取并保存手机号归属地和运营商的示例
Oct 09 Python
python获取天气接口给指定微信好友发天气预报
Dec 28 Python
Python多进程写入同一文件的方法
Jan 14 #Python
python 将大文件切分为多个小文件的实例
Jan 14 #Python
使用k8s部署Django项目的方法步骤
Jan 14 #Python
Python数据可视化教程之Matplotlib实现各种图表实例
Jan 13 #Python
python中使用 xlwt 操作excel的常见方法与问题
Jan 13 #Python
用Python实现大文本文件切割的方法
Jan 12 #Python
python实时获取外部程序输出结果的方法
Jan 12 #Python
You might like
php简单对象与数组的转换函数代码(php多层数组和对象的转换)
2011/05/18 PHP
PHP字符串函数系列之nl2br(),在字符串中的每个新行 (\n) 之前插入 HTML 换行符br
2011/11/10 PHP
PHP获取数组中某元素的位置及array_keys函数应用
2013/01/29 PHP
解析PHP跨站刷票的实现代码
2013/06/18 PHP
ThinkPHP中的create方法与自动令牌验证实例教程
2014/08/22 PHP
php常用hash加密函数
2014/11/22 PHP
CI框架教程之优化验证码机制详解【验证码辅助函数】
2019/04/16 PHP
XHTML-Strict 内允许出现的标签
2006/12/11 Javascript
js 操作select相关方法函数
2009/12/06 Javascript
Javascript Math ceil()、floor()、round()三个函数的区别
2010/03/09 Javascript
css样式标签和js语法属性区别
2013/11/06 Javascript
如何实现修改密码时密码框显示保存到cookie的密码
2013/12/10 Javascript
JS返回iframe中frameBorder属性值的方法
2015/04/01 Javascript
jQuery实现动态添加和删除一个div
2015/08/12 Javascript
简单谈谈node.js 版本控制 nvm和 n
2015/10/15 Javascript
跟我学习javascript的函数调用和构造函数调用
2015/11/16 Javascript
基于Bootstrap实现的下拉菜单手机端不能选择菜单项的原因附解决办法
2016/07/22 Javascript
JavaScript对象创建模式实例汇总
2016/10/03 Javascript
ES6概念 Symbol toString()方法
2016/12/25 Javascript
深入理解Nodejs Global 模块
2017/06/03 NodeJs
vue+axios 前端实现的常用拦截的代码示例
2018/08/23 Javascript
JS常用正则表达式超全集(密码强度校验,金额校验,IE版本,IPv4,IPv6校验)
2020/02/03 Javascript
JS控制下拉列表左右选择实例代码
2020/05/08 Javascript
JavaScript中window和document用法详解
2020/07/28 Javascript
Python实现竖排打印传单手机号码易撕条
2015/03/16 Python
python自带的http模块详解
2016/11/06 Python
Python使用Pickle模块进行数据保存和读取的讲解
2019/04/09 Python
pycharm 的Structure界面设置操作
2021/02/05 Python
CSS3教程(5):网页背景图片
2009/04/02 HTML / CSS
HTML5 Canvas+JS控制电脑或手机上的摄像头实例
2014/05/03 HTML / CSS
会计师职业生涯规划范文
2014/02/18 职场文书
党的群众路线教育实践活动总结报告
2014/07/03 职场文书
2016春季田径运动会广播稿
2015/12/21 职场文书
《角的度量》教学反思
2016/02/18 职场文书
创业者如何撰写出一份打动投资人的商业计划书?
2019/07/02 职场文书
怎样做好公众演讲能力?
2019/08/28 职场文书