技术标签: python # Python 多线程编程 多线程 threading 后端 开发语言
目 录
Python 多线程编程目录
Python 多线程编程-01-threading 模块初识
Python 多线程编程-02-threading 模块-锁的使用
Python 多线程编程-03-threading 模块 - Condition
Python 多线程编程-04-threading 模块 - Event
Python 多线程编程-05-threading 模块 - Semaphore 和 BoundedSemaphore
Python 多线程编程-06-threading 模块 - Timer
Python 多线程编程-07-threading 模块 - Barrier
前面两章已经说过 threading 模块中互斥锁的使用,不管是 threading.Lock 还是 threading.RLock,这种互斥锁是最简单的线程同步机制,在实际工作中会有很多复杂情况是互斥锁无法解决的。而Python 提供的 Condition 对象提供了对复杂线程同步问题的支持。
常见的生产者消费者模型具体来讲,就是在一个系统中,存在生产者和消费者两种角色,它们通过内存缓冲区进行通信,生产者生产消费者需要的资料,消费者消耗生成的资料,生产者和消费者之间共享的内存缓冲池大小可变,生产者数量可变,消费者数量可变。
像这类问题,用简单的互斥锁就比较难以解决。
Condition 被称为条件变量,可以理解为一种进阶的锁,使用的基本原理如下:
1、Condition对象的构造函数可以接受一个 Lock/RLock 对象作为参数,如果没有指定,则默认是可重入锁 RLock,生成的 Condition 对象会维护一个 Lock/RLock 和一个 waiting 池。
2、线程调用 acquire 方法获得 Condition 对象,这一点和 Lock/RLock类似 。
# wait() 方法、notify() 方法、notifiy_all() 方法都只能在线程调用 acquire 方法之后,线程调用 release 方法之前!
3、线程调用 wait 方法时,线程会释放 Condition 内部的锁并进入 blocked 状态,同时在waiting 池中记录这个线程。
4、线程调用 notify/notify_all 方法时,Condition 对象会从 waiting 池中挑选一个线程,通知其调用 acquire 方法尝试取到锁。线程只能通过notify方法唤醒,所以notifyAll的作用在于防止有的线程永远处于沉默状态。
5、线程调用 release 方法释放 Condition 对象
Condition 被称为条件变量,除了提供与 Lock、RLock 类似的 acquire() 和 release() 方法外,还提供了 wait() 、notify()、notifyAll() 方法。
序号 | 属性和方法 | 描述 |
1 | acquire (blocking=True) |
锁住这个 Condidtion,然后返回一个布尔值。 `blocking` 指示这个 Condition 无法锁定时候,是否阻塞线程。 如果 `blocking` 是 False 且另外一个线程锁定了这个 Conditon,那么立刻返回 False。 如果 `blocking` 是 True 且另外一个线程锁定了这个 Conditon,那么则阻塞这个线程直到 Condition 被释放,获得之并返回 True。阻塞过程是可以被打断。 这意味着 Conditon 是可重入的。 |
2 | release() | 释放这个 Condition,允许在阻塞等待队列中的其他线程获得该 Condition。这个 Condition 此刻必须在被锁定的状态,且是被同一个线程给锁定的,否则返回 RuntimeError。 请注意,如果这个 Condition 被同一个线程锁定了多次,那么也需要 release 多次才行。 |
3 | notify(n=1) | 唤醒一个或者多个在等待这个 Condition 的线程。如果被唤醒的线程没有acquire 这个 Condition,那么报 RuntimeError。 这个方法最多唤醒 n 个 线程。如果没有线程等待,则无作为。 |
4 | notifyAll() | 唤醒所有在等待这个 Condition 的线程。如果被唤醒的线程没有锁定这个 Condition,那么报 RuntimeError。 |
5 | wait (timeout=None) |
阻塞等待直到该 Condition 释放或者 timeout 到期。 如果被唤醒的线程没有acquire 这个 Condition,那么报 RuntimeError。 当基础锁是RLock时,不会使用其 release() 方法,因为这可能不会在打开锁时实际解锁多次递归获取。而是一个内部接口使用 RLock 类的多次被递归获取。另一个内部接口是然后用于在重新获取锁时恢复递归级别。 |
6 | wait_for(predicate, timeout=None) | 等待直到条件变为 True。predicate 应该是一个可调用对象,且其结果为一个布尔值。timeout 用于给定最长的等待时长。 |
下面的代码以生产者-消费者为例子,一个资源池最多可以存放 5 个物品,一次生产线程最多生成 5 个物品,消费者每次是取走一个物品,如果资源池中少于4个物品,则提醒生产线程继续生成物品。
请注意 Producer 中的等待代码 self.con.wait(),没有使用 timeout,这样它是会一直阻塞等待的。
而 Consumer 中的等待代码 self.con.wait(6),等到6秒后自动解除阻塞等待状态,请大家想想是为什么。
import threading
import time
max_goods_num=10
min_goods_num=4
con = threading.Condition()
num = 0
class Producer(threading.Thread):
def __init__(self, con):
self.con = con
super().__init__()
def run(self):
global num
print("*"*50)
print("Coming in Producer ",time.ctime())
self.con.acquire()
for _ in range(max_goods_num):
print("----------进入循环生成物品程序------------")
print("开始生成物品")
num += 1
print("资源池里面物品的个数为:{}".format(num))
time.sleep(1)
if num == 5:
print("资源池里面物品的个数已经到达五个, 无法继续生成了")
self.con.notify()
self.con.wait()
self.con.release()
print("Producer run exit")
class Consumer(threading.Thread):
def __init__(self, con):
self.con = con
super().__init__()
def run(self):
print("*"*50)
print("Coming in Consumer ",time.ctime())
self.con.acquire()
global num
while num:
print("----------进入循环消耗物品程序------------")
num -= 1
print("资源池里面物品剩余:{}".format(num))
time.sleep(0.5)
if num <min_goods_num :
print("资源池里面物品数量小于 min_goods_num,需要添加!")
self.con.notify()
self.con.wait(6)
self.con.release()
print("Consumer run exit")
p = Producer(con)
c = Consumer(con)
p.start()
c.start()
'''
要是大家觉得写得还行,麻烦点个赞或者收藏吧,想个博客涨涨人气,非常感谢!
'''
文章浏览阅读2.7k次,点赞2次,收藏4次。这是因为时区问题 咱们这是东八区(&serverTimezone=GMT%2B8,数据库的配置,意思即为东八区北京时间)今天这是在使用springboot向小程序前端返回时间格式的数据时发现的问题。这是因为在springboot中,无论时Controller还是RestController他们的返回类型都是Json类型的,而springboot默认的是Jackson框架转换,而J..._pgsql的date类型后台返回时间正常前端使用时间有误
文章浏览阅读193次。计算机视觉(一)-openCV的安装及使用下面链接是我博客园网址,对opencv安装以及配置VS2019环境进行了详细的说明,欢迎大家阅读:地址_kali opencv
文章浏览阅读7.4k次,点赞2次,收藏23次。承接上篇博客null试了很久,发现是sleep()函数问题。我不太清楚是什么问题,就是程序运行一段时间就停止了,也不会报错,有大佬知道是为什么的可以说一下么,谢谢了。下面是我实现的MQTT订阅消息代码。import paho.mqtt.client as mqttfrom datetime import datetimeimport jsonimport timeimport pymysql as MySQLdbMQTTHOST = "192.168.31.67"MQTTPORT = 1883mqttClh_python mqtt 多线程
文章浏览阅读3.4k次,点赞2次,收藏11次。整合一个编辑器,其实很简单。首先找到他的源码,以editor.md 为例:https://github.com/pandao/editor.md 下载后,到examples文件夹看看,看到一个simple.html的例子,这就是可以复制的前端代码:到myeclipse中新建一个应用, 并添加spring支持(公司用jdk1.7,就简单用spring4.2.5, 不用spring boot..._spring引入markdown
文章浏览阅读165次。2-1 线性表抽象数据类型线性表定义:0个 or 多个数据元素的有限序列特点:是一个序列 元素之间是有序的 数据元素 之间是 一对一的关系有限性: 线性表的数据元素的个数是有限的 (食物链中生物的个数是有限的)常见的操作创建和初始化 、 查找 、 插入 、 删除(增删改查)线性表表达:ADT 线性表(SequenceList) //线性表Data 1..._include
文章浏览阅读190次。1.发布订阅者我们已经知道实现数据的双向绑定,首先要对数据进行劫持监听,需要设置一个监听器Observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者Watcher看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器Dep来专门收集这些订阅者,然后在监听器(发布者)Observer和订阅者Watcher之间进行统一管理的。接着,我们还需要有一个指令解析器Compile,..._var name = "小白"; var obj = { name: "小红" }; function sayname() { return t
文章浏览阅读292次。摘要: Java实现生产者消费者问题与读者写者问题1、生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。解决生产者/消费者问题的方法可分为两类:(1)采用某种机制保护生产者和消费者之间的同步;(2)在生产者和消费者之间建立一个管道。第一种方式有较高的效_读写者问题和消费者生产者问题哪个好实现
文章浏览阅读387次。CanvasUpdate枚举类:CanvasUpdate,用于表示当前的布局阶段public enum CanvasUpdate{ /// <summary> /// Called before layout. /// </summary>Prelayout= 0, /// <summary> /// Called for layout. /// </summary>Layout= 1, ///_graphicupdatecomplete
文章浏览阅读324次。 不多说,直接上干货! 前期博客 Ambari安装之部署本地库(镜像服务器)(二) 安装并配置Ambari-server(1)检查仓库是否可用 [hadoop@ambari01 yum.repos.d]$ pwd/etc/yum.repos.d[hadoop@ambari01 yum.repos.d]$ y..._怎么确定ambari server
文章浏览阅读967次。报错kernel:NMI watchdog: BUG: soft lockup - CPU#0 stuck for 26s故障背景近期在服务器跑大量高负载程序,造成cpu soft lockup。如果确认不是软件的问题。解决方法#追加到配置文件中echo 30 > /proc/sys/kernel/watchdog_thresh #查看[root@git-node1 data]# tail -1 /proc/sys/kernel/watchdog_thresh30#临时生效_kernel:nmi watchdog: bug: soft lockup - cpu#0 stuck for
文章浏览阅读3.7k次。aAxis:{ show:true,//false data:['1月','2月','3月'], boundaryGap:false,// true | ['30%', '20%'],x轴两边是否留白,true留白,false不留白}_echarts x轴坐标样式
文章浏览阅读249次。一直觉得Qt的帮助文档的样式完美的长在了我的审美点上,因此在使用MarkDown编写自己的文档时也喜欢做成类似于Qt帮助文档的样式_markdown转qt help