对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实现向ppt文件里插入新幻灯片页面的方法
Apr 28 Python
python检查序列seq是否含有aset中项的方法
Jun 30 Python
详解python之配置日志的几种方式
May 22 Python
python 删除列表里所有空格项的方法总结
Apr 18 Python
Python父目录、子目录的相互调用方法
Feb 16 Python
对Python3 * 和 ** 运算符详解
Feb 16 Python
python递归法解决棋盘分割问题
Jul 17 Python
tensorflow实现测试时读取任意指定的check point的网络参数
Jan 21 Python
Pycharm如何运行.py文件的方法步骤
Mar 03 Python
经验丰富程序员才知道的8种高级Python技巧
Jul 27 Python
如何实现一个python函数装饰器(Decorator)
Oct 12 Python
Python中else的三种使用场景
Jun 16 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技术开发客服工单系统
2016/01/06 PHP
基于jquery实现的仿优酷图片轮播特效代码
2016/01/13 Javascript
AngularJs学习第八篇 过滤器filter创建
2016/06/08 Javascript
基于js里调用函数时,函数名带括号和不带括号的区别
2016/07/28 Javascript
浅析Javascript ES6中的原生Promise
2016/08/25 Javascript
纯JavaScript 实现flappy bird小游戏实例代码
2016/09/27 Javascript
JS实现图片垂直居中显示小结
2016/12/13 Javascript
babel之配置文件.babelrc入门详解
2018/02/22 Javascript
微信小程序支付功能 php后台对接完整代码分享
2018/06/12 Javascript
详解微信小程序input标签正则初体验
2018/08/18 Javascript
vue+elementUi图片上传组件使用详解
2019/08/20 Javascript
vue使用nprogress实现进度条
2019/12/09 Javascript
[04:27]DOTA2官方论坛水友赛集锦
2013/09/16 DOTA
python遍历类中所有成员的方法
2015/03/18 Python
Python基于scrapy采集数据时使用代理服务器的方法
2015/04/16 Python
Python3安装Pymongo详细步骤
2017/05/26 Python
微信跳一跳辅助python代码实现
2018/01/05 Python
python机器人行走步数问题的解决
2018/01/29 Python
python实现寻找最长回文子序列的方法
2018/06/02 Python
python文件操作seek()偏移量,读取指正到指定位置操作
2020/07/05 Python
Python pickle模块常用方法代码实例
2020/10/10 Python
一个非常简单好用的Python图形界面库(PysimpleGUI)
2020/12/28 Python
html5视频播放_动力节点Java学院整理
2017/07/13 HTML / CSS
HTML5地理定位_动力节点Java学院整理
2017/07/12 HTML / CSS
澳大利亚婴儿喂养品牌:Cherub Baby
2018/11/01 全球购物
Arti-shopping中文官网:大型海外商品一站式直邮平台
2020/03/23 全球购物
什么是典型的软件三层结构?软件设计为什么要分层?软件分层有什么好处?
2012/03/14 面试题
预备党员入党思想汇报
2014/01/04 职场文书
幼儿园托班开学寄语
2014/01/18 职场文书
护士辞职信范文
2014/01/19 职场文书
服务宗旨标语
2014/07/01 职场文书
现实表现材料范文
2014/12/23 职场文书
幼儿园中班教师个人总结
2015/02/05 职场文书
兼职安全员岗位职责
2015/02/15 职场文书
民事答辩状格式范文
2015/05/21 职场文书
Python数据分析之pandas函数详解
2021/04/21 Python