python多线程之线程锁(Lock)和递归锁(RLock)实例

 

 

一、线程锁

Threading模块为我们提供了一个类,Threading.Lock锁。我们创建一个该类对象,在线程函数执行前,“抢占”该锁,执行完成后,“释放”该锁,则我们确保了每次只有一个线程占有该锁。这时候对一个公共的对象进行操作,则不会发生线程不安全的现象了。

1、我们先建立了一个threading.Lock类对象lock,在run方法里,我们使用lock.acquire()获得了这个锁。此时,其他的线程就无法再获得该锁了,他们就会阻塞在“if lock.acquire()”这里,直到锁被另一个线程释放:lock.release()。

2、如果多个线程要调用多个现象,而A线程调用A锁占用了A对象,B线程调用了B锁占用了B对象,A线程不能调用B对象,B线程不能调用A对象,于是一直等待。这就造成了线程“死锁”。

Threading模块中,也有一个类,RLock,称之为可重入锁。该锁对象内部维护着一个Lock和一个counter对象。counter对象记录了acquire的次数,使得资源可以被多次require。最后,当所有RLock被release后,其他线程才能获取资源。在同一个线程中,RLock.acquire可以被多次调用,利用该特性,可以解决部分死锁问题

3、当多个线程同时访问一个数据时,需加锁,排队变成单线程一个一个执行

4、加锁避免并发导致逻辑出错

5、每当一个线程a要访问共享数据时,必须先获得锁定;如果已经有别的线程b获得锁定了,那么就让线程a暂停,也就是同步阻塞;等到线程b访问完毕,释放锁以后,再让线程a继续

6、语法

lock=threading.Lock() #创建线程锁

lock = threading.RLock()#创建递归锁(多个锁时用这个)

lock.acquire() #锁住

lock.release() 释放锁

 

二、线程锁实例

#未加锁
如果多个线程同时操作某个数据,会出现不可预料的结果。比如以下场景:当小伙伴a在往火锅里面添加鱼丸的时候,小伙伴b在同时吃掉鱼丸,这很有可能导致刚下锅的鱼丸被夹出来了(没有熟),或者还没下锅,就去夹鱼丸(夹不到)# coding=utf-8
import threading
import time
def chiHuoGuo(people, do):print("%s 吃火锅的小伙伴:%s" % (time.ctime(),people))time.sleep(1)for i in range(3):time.sleep(1)print("%s %s正在 %s 鱼丸"% (time.ctime(), people, do))print("%s 吃火锅的小伙伴:%s" % (time.ctime(),people))
class myThread (threading.Thread):   # 继承父类threading.Threaddef __init__(self, people, name, do):'''重写threading.Thread初始化内容'''threading.Thread.__init__(self)self.threadName = nameself.people = peopleself.do = dodef run(self):   # 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数'''重写run方法'''print("开始线程: " + self.threadName)chiHuoGuo(self.people, self.do)     # 执行任务print("结束线程: " + self.name)
print("yoyo请小伙伴开始吃火锅:!!!")
# 设置线程组
threads = []
# 创建新线程
thread1 = myThread("xiaoming", "Thread-1", "添加")
thread2 = myThread("xiaowang", "Thread-2", "吃掉")
# 添加到线程组
threads.append(thread1)
threads.append(thread2)
# 开启线程
for thread in threads:thread.start()
# 阻塞主线程,等子线程结束
for thread in threads:thread.join()
time.sleep(0.1)
print("退出主线程:吃火锅结束,结账走人")C:\Users\wangli\PycharmProjects\AutoMation\venv\Scripts\python.exe C:/Users/wangli/PycharmProjects/AutoMation/case/test.py
yoyo请小伙伴开始吃火锅:!!!
开始线程: Thread-1
Fri Mar 15 08:33:19 2019 吃火锅的小伙伴:xiaoming
开始线程: Thread-2
Fri Mar 15 08:33:19 2019 吃火锅的小伙伴:xiaowang
Fri Mar 15 08:33:21 2019 xiaowang正在 吃掉 鱼丸
Fri Mar 15 08:33:21 2019 xiaoming正在 添加 鱼丸
Fri Mar 15 08:33:22 2019 xiaowang正在 吃掉 鱼丸
Fri Mar 15 08:33:22 2019 xiaoming正在 添加 鱼丸
Fri Mar 15 08:33:23 2019 xiaowang正在 吃掉 鱼丸
Fri Mar 15 08:33:23 2019 吃火锅的小伙伴:xiaowang
结束线程: Thread-2
Fri Mar 15 08:33:23 2019 xiaoming正在 添加 鱼丸
Fri Mar 15 08:33:23 2019 吃火锅的小伙伴:xiaoming
结束线程: Thread-1
退出主线程:吃火锅结束,结账走人Process finished with exit code 0
#线程锁,单锁实例
import time,threading
def run(n):lock.acquire() #加锁global numnum+=1lock.release() #释放锁
lock=threading.Lock()#获得线程锁
num=0
threads=[]
for i in range(50):thread=threading.Thread(target=run,args=("t-%s"%i,))thread.start()threads.append(thread)
for i in threads:i.join()
print("num:",num)C:\Users\wangli\PycharmProjects\AutoMation\venv\Scripts\python.exe C:/Users/wangli/PycharmProjects/AutoMation/case/test.py
num: 50Process finished with exit code 0
#线程锁,加锁实例# coding=utf-8
import threading
import time
def chiHuoGuo(people, do):print("%s 吃火锅的小伙伴:%s" % (time.ctime(),people))time.sleep(1)for i in range(3):time.sleep(1)print("%s %s正在 %s 鱼丸"% (time.ctime(), people, do))print("%s 吃火锅的小伙伴:%s" % (time.ctime(),people))
class myThread (threading.Thread):   # 继承父类threading.Threadlock = threading.Lock()  # 线程锁def __init__(self, people, name, do):'''重写threading.Thread初始化内容'''threading.Thread.__init__(self)self.threadName = nameself.people = peopleself.do = dodef run(self):   # 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数'''重写run方法'''print("开始线程: " + self.threadName)# 执行任务之前锁定线程self.lock.acquire()chiHuoGuo(self.people, self.do)     # 执行任务# 执行完之后,释放锁self.lock.release()print("结束线程: " + self.name)
print("yoyo请小伙伴开始吃火锅:!!!")
# 设置线程组
threads = []
# 创建新线程
thread1 = myThread("xiaoming", "Thread-1", "添加")
thread2 = myThread("xiaowang", "Thread-2", "吃掉")
# 添加到线程组
threads.append(thread1)
threads.append(thread2)
# 开启线程
for thread in threads:thread.start()
# 阻塞主线程,等子线程结束
for thread in threads:thread.join()
time.sleep(0.1)
print("退出主线程:吃火锅结束,结账走人")C:\Users\wangli\PycharmProjects\AutoMation\venv\Scripts\python.exe C:/Users/wangli/PycharmProjects/AutoMation/case/test.py
yoyo请小伙伴开始吃火锅:!!!
开始线程: Thread-1
Fri Mar 15 08:36:39 2019 吃火锅的小伙伴:xiaoming
开始线程: Thread-2
Fri Mar 15 08:36:41 2019 xiaoming正在 添加 鱼丸
Fri Mar 15 08:36:42 2019 xiaoming正在 添加 鱼丸
Fri Mar 15 08:36:43 2019 xiaoming正在 添加 鱼丸
Fri Mar 15 08:36:43 2019 吃火锅的小伙伴:xiaoming
结束线程: Thread-1
Fri Mar 15 08:36:43 2019 吃火锅的小伙伴:xiaowang
Fri Mar 15 08:36:45 2019 xiaowang正在 吃掉 鱼丸
Fri Mar 15 08:36:47 2019 xiaowang正在 吃掉 鱼丸
Fri Mar 15 08:36:48 2019 xiaowang正在 吃掉 鱼丸
Fri Mar 15 08:36:48 2019 吃火锅的小伙伴:xiaowang
结束线程: Thread-2
退出主线程:吃火锅结束,结账走人Process finished with exit code 0
#线程锁,多个锁时,需加递归锁import threading, time
def run1():print("grab the first part data")lock.acquire()global numnum += 1lock.release()return num
def run2():print("grab the second part data")lock.acquire()global num2num2 += 1lock.release()return num2
def run3():lock.acquire()res = run1()print('--------between run1 and run2-----')res2 = run2()lock.release()print(res, res2)
num, num2 = 0, 0
lock = threading.RLock() #递归锁
for i in range(3):t = threading.Thread(target=run3)t.start()
while threading.active_count() != 1:print(threading.active_count())
else:print('----all threads done---')print(num, num2)

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/568499.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

并发编程:进程,线程,协程,异步

并发编程(不是并行)目前有四种方式:多进程、多线程、协程和异步。 多进程编程在python中有类似C的os.fork,更高层封装的有multiprocessing标准库多线程编程python中有Thread和threading异步编程在linux下主要有三种实现select,po…

jmeter环境部署

win环境下: 1、复制jmeter整个包到本地解压、安装jdk 2、jdk环境环境变量配置(电脑-属性-高级系统设置-环境变量) 系统变量JAVA_HOME 变量值C:\Program Files\Java\jdk1.8.0_101 用户变量path 变量值%JAVA_HOME%\bin cmd下输java或jav…

【Python】pdf2image模块+poppler将PDF转换为图片

有时我们需要将PDF转换成图片,今天我们主要说的是pdf2imagepoppler对PDF转换成图片格式。 pdf2image是个包装器,真正的转换工具是poppler GitHub地址:https://github.com/Belval/pdf2image ,上面也有相关的配置说明。 1、安装pdf…

jmeter五种参数化方式之CSV Data Set Config参数化

一、用户定义的变量 一般会设置全局不变的参数,如host、账号、密码等 设置名称username,password 值王荔,123456 线程设置2次和循环设置2次,2次采样器传参和结果一样 二、用户参数 添加用户参数 设置3组参数 参数化 当线程设置…

【Python】PyMuPDF模块将PDF转换为图片

上一篇文章介绍了pdf2image模块poppler将PDF转换为图片,这篇文章主要介绍另外一个模块PyMuPDF。 PyMuPDF(又名“fitz”):MuPDF的Python绑定,它是一个轻量级的PDF和XPS查看器。该库可以访问PDF,XPS&#xf…

【Liunx服务器】阿里云服务器下部署多个tomcat服务

现在有这样一个场景,一个阿里云服务器上面已经有tomcat项目和多个maven项目,现在需要在一个新项目中配置一个空的tomcat,现将具体流程记录下来。 1.下载tomcat包或者找到已下载的包 2.将tomcat的包解压到指定项目目录:/data/proj…

【测试】身份证的前世今生

在我们的测试中,经常要校验身份证的有效性,但是我们大多数人并不清楚身份证具体是如何组成的,有什么特点,下面我们就了解一下它的前世今生。 身份证由来 从1999年10月1日起,全国实行公民身份证号码制度,居民身份证编号由原15位升至18位。 根据〖中华人民共和国国家标准…

C++根据输入日期YYYY-MM-DD判断是否星期几

参考链接: https://blog.csdn.net/bible521125/article/details/50418436 https://blog.csdn.net/tojohnonly/article/details/78326633 https://blog.csdn.net/fengbingchun/article/details/54835571

【音频】音频文件格式以及相关参数

音频是个专业术语,音频一词已用作一般性描述音频范围内和声音有关的设备及其作用。人类能够听到的所有声音都称之为音频,它可能包括噪音等。 声音被录制下来以后,无论是说话声、歌声、乐器都可以通过数字音乐软件处理,或是把它制作…

python 按照当前日期创建文件

import time import os.path#获得当前系统时间的字符串 localtimetime.strftime(%Y-%m-%d %H:%M:%S,time.localtime(time.time())) print(localtimelocaltime) #系统当前时间年份 yeartime.strftime(%Y,time.localtime(time.time())) #月份 monthtime.strftime(%m,time.localti…

【Python】Python中内置的%操作符

Python中内置的%操作符可用于格式化字符串操作,控制字符串的呈现格式。Python中还有其他的格式化字符串的方式,但%操作符的使用是最方便的。 格式符为真实值预留位置,并控制显示的格式。格式符可以包含有一个类型码,用以控制显示的…

数据结构二叉树遍历求后序

注意左右子树的递归 参考自https://blog.csdn.net/hou_blog/article/details/50015503

python queue队列

作用: 解耦:使程序直接实现松耦合,修改一个函数,不会有串联关系。 提高处理效率:FIFO = 现进先出,LIF&#…

【Python】ffmpeg模块查询视频、音频信息

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。 它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量&#xff…

log4j学习

依赖 <!--log4j依赖--> <dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version> </dependency><!--测试--> <dependency><groupId>org.junit.jupiter</g…

navicat连接远程mysql数据库

前提&#xff1a;保证你的navicat数据是允许外界可以连接 1.保证两台电脑应在同一局域网内 2.查询被连接数据库电脑的ip 3.在连接端&#xff0c;主机那个填入ip地址&#xff0c;用户名&#xff0c;密码等信息。测试连接 4、连接成功后&#xff0c;用此ip即为连接数据库的ho…

【Python】ffmpeg模块处理视频、音频信息

多媒体视频处理工具FFmpeg有非常强大的功能包括视频采集功能、视频格式转换、视频抓图、给视频加水印等。 这里主要介绍一下FFmpeg的一些常用参数&#xff0c;并且主要功能&#xff1a;截取视频、视频格式转换、视频分辨率转换、视频合并、提取视频、提取音频、提取图片、视频水…

【探索测试篇】探索无界,BUG无限,让程序猿头疼的测试技术

探索无界&#xff0c;BUG无限 一、修改系统时间 当功能模块中存在倒计时、计时器、时间&#xff0c;与时间有关系时&#xff0c;尝试修改系统时间&#xff0c;测试系统时间是否参与计算&#xff0c;修改系统时间是否会影响到倒计时、计时、时间等与时间有关系的模块 例&#…

【数据库】Mysql函数DATE_ADD() 增加日期/时间

有这样一个场景&#xff1a;数据库还款计划表有到期还款日字段&#xff0c;正常是每月2日。但这个字段有些是每月1日&#xff0c;现需要统一改成2日&#xff0c;可以用到DATE_ADD函数&#xff0c;但是执行时需要注意&#xff1a;只能执行一次 DATE_ADD(date,INTERVAL expr type…

python 时间函数小总结

时间戳&#xff1a;从1970年1月1日00:00:00开始按秒计算的偏移量。举个例子&#xff0c;现在是2017年6月11的下午16:54:32&#xff0c;那么print(time.time())输出的值是1497171320.99就代表现在的时间戳。 元组&#xff08;struct_time&#xff09;&#xff1a;struct_time元组…