对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之传说中的函数编写条规
Oct 11 Python
Python 专题四 文件基础知识
Mar 20 Python
pyqt5简介及安装方法介绍
Jan 31 Python
python 正确保留多位小数的实例
Jul 16 Python
Flask Web开发入门之文件上传(八)
Aug 17 Python
Python 实现两个列表里元素对应相乘的方法
Nov 14 Python
python根据url地址下载小文件的实例
Dec 18 Python
Flask之请求钩子的实现
Dec 23 Python
python读写csv文件实例代码
Jul 05 Python
python写一个随机点名软件的实例
Nov 28 Python
python能否java成为主流语言吗
Jun 22 Python
python七种方法判断字符串是否包含子串
Aug 18 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自动适应范围的分页代码
2008/08/05 PHP
php写的AES加密解密类分享
2014/06/20 PHP
Yii使用Captcha验证码的方法
2015/12/28 PHP
Thinkphp 框架配置操作之动态配置、扩展配置及批量配置实例分析
2020/05/15 PHP
html中table数据排序的js代码
2011/08/09 Javascript
多浏览器兼容性比较好的复制到剪贴板的js代码
2011/10/09 Javascript
jQuery ajax(复习)—Baidu ajax request分离版
2013/01/24 Javascript
jQuery创建平滑的页面滚动(顶部或底部)
2013/02/26 Javascript
js函数调用的方式
2014/05/06 Javascript
NodeJs中的VM模块详解
2015/05/06 NodeJs
图解JavaScript中的this关键字
2020/05/28 Javascript
JQuery实现简单的服务器轮询效果实例
2016/03/31 Javascript
JavaScript弹窗基础篇
2016/04/27 Javascript
模拟javascript中的sort排序(简单实例)
2016/08/17 Javascript
基于JavaScript实现自动更新倒计时效果
2016/12/19 Javascript
详解cordova打包成webapp的方法
2017/10/18 Javascript
微信小程序之自定义组件的实现代码(附源码)
2018/08/02 Javascript
关于layui时间回显问题的解决方法
2019/09/24 Javascript
js实现内置计时器
2019/12/16 Javascript
python中将一个全部为int的list 转化为str的list方法
2018/04/09 Python
Python合并多个Excel数据的方法
2018/07/16 Python
Python+redis通过限流保护高并发系统
2020/04/15 Python
Python3.7安装PyQt5 运行配置Pycharm的详细教程
2020/10/15 Python
Django-silk性能测试工具安装及使用解析
2020/11/28 Python
HTML5 拖放功能实现代码
2016/07/14 HTML / CSS
日本食品网上商店:JaponShop.com
2017/11/28 全球购物
大学生工作推荐信范文
2013/12/02 职场文书
运动会广播稿300字
2014/01/10 职场文书
股权转让协议书
2014/04/12 职场文书
公司员工安全协议书
2014/11/21 职场文书
应届毕业生求职信范文
2015/03/19 职场文书
公司聚餐通知
2015/04/22 职场文书
工作调动申请报告
2015/05/18 职场文书
《鲸》教学反思
2016/02/23 职场文书
golang生成vcf通讯录格式文件详情
2022/03/25 Golang
向Spring IOC 容器动态注册bean实现方式
2022/07/15 Java/Android