Condition常用于生产者、消费者模型,为了解决生产者消费者速度匹配问题。

构造方法Condition(lock=None),可以传入一个Lock或RLock对象,默认RLock。

方法:

acquire(*args)  获取锁

release()     释放锁

wait(timeout=None)  等待通知或直到发生超时

notify(n=1)  唤醒至多指定个数的等待的线程,没有等待的线程就没有任何操作

notify_all()  唤醒所有等待的线程。wake up

以下例子,不考虑线程安全问题:

例1:

#Condition
import threading,random,logging
logging.basicConfig(level=logging.INFO) class Dispatcher:
def __init__(self):
self.data = 0
self.event = threading.Event() def produce(self):
for i in range(100):
self.event.wait(1) #每1秒生成一条数据
data = random.randint(1,100)
self.data = data def custom(self):
while True:
logging.info(self.data)
self.event.wait(0.5) # 替换为1表示消费者每1秒取一次数据 d = Dispatcher()
p = threading.Thread(target=d.produce)
c = threading.Thread(target=d.custom) c.start()
p.start() 以下结果:
INFO:root:0
INFO:root:0
INFO:root:0
INFO:root:77
INFO:root:64
INFO:root:64
INFO:root:8
INFO:root:8
INFO:root:85

  生产者每1秒钟生成一条数据,消费者每0.5秒就来取一次数据。

例2:

#Condition 通知机制,解决重复
import threading,random,logging
logging.basicConfig(level=logging.INFO) class Dispatcher:
def __init__(self):
self.data = 0
self.event = threading.Event()
self.cond = threading.Condition() def produce(self):
for i in range(100):
data = random.randint(1,100)
with self.cond:
self.data = data
self.cond.notify_all() #通知所有waiter
self.event.wait(1) #1秒生产一次数据 def custom(self):
while True:
with self.cond:
self.cond.wait() #无限等待
logging.info(self.data) #消费 self.event.wait(0.5) #0.5秒消费一次数据 d = Dispatcher()
p = threading.Thread(target=d.produce)
c = threading.Thread(target=d.custom) c.start()
p.start() 运行结果:
INFO:root:64
INFO:root:43
INFO:root:11
INFO:root:28
INFO:root:30
INFO:root:33
INFO:root:93
INFO:root:69
INFO:root:4

  使用with来管理Condition的上下文(acquire/release),利用Condition通知机制解决消费者获取重复数据。

例3:

#Condition 先生成后消费,1对1
import threading,random,logging
logging.basicConfig(level=logging.INFO,format="%(thread)d %(threadName)s %(message)s") class Dispatcher:
def __init__(self):
self.data = 0
self.event = threading.Event()
self.cond = threading.Condition() def produce(self):
for i in range(100):
data = random.randint(1,100)
logging.info(self.data)
with self.cond:
self.data = data
self.cond.notify(1)
# self.cond.notify_all()
self.event.wait(1) def custom(self):
while True:
with self.cond:
self.cond.wait()
logging.info(self.data) self.event.wait(0.5) d = Dispatcher()
p = threading.Thread(target=d.produce,name='produce')
c = threading.Thread(target=d.custom,name='c')
c1 = threading.Thread(target=d.custom,name='c1')
p.start() e = threading.Event()
e.wait(3) c1.start()
c.start() 运行结果:
7520 produce 0
7520 produce 78
7520 produce 88
7520 produce 14
7520 produce 83
2508 c1 86
7520 produce 86
1136 c 79
7520 produce 79
2508 c1 77
7520 produce 77
1136 c 47
7520 produce 47
2508 c1 76
7520 produce 76
1136 c 69

  生产者先生产数据,2个消费者一个一个来消费数据。

例4:

#Condition 1对多,2个2个通知
import threading,random,logging
logging.basicConfig(level=logging.INFO,format="%(thread)d %(threadName)s %(message)s") class Dispatcher:
def __init__(self):
self.data = 0
self.event = threading.Event()
self.cond = threading.Condition() def produce(self):
for i in range(100):
data = random.randint(1,100)
logging.info(self.data)
with self.cond:
self.data = data
self.cond.notify(2)
# self.cond.notify_all()
self.event.wait(1) def custom(self):
while True:
with self.cond:
self.cond.wait()
logging.info(self.data)
# self.event.wait(0.5) d = Dispatcher()
p = threading.Thread(target=d.produce,name='produce') for i in range(5):
threading.Thread(target=d.custom,name='c-{}'.format(i)).start() p.start() 以下结果:
8688 produce 0
10376 c-0 90
7928 c-1 90
8688 produce 90
7640 c-2 61
10748 c-3 61
8688 produce 61
10376 c-0 73
1344 c-4 73
8688 produce 73
7928 c-1 57
7640 c-2 57
8688 produce 57
10748 c-3 71
10376 c-0 71

  1对多,2个2个通知来处理数据。

以上例子中,程序本身不是线程安全的,程序逻辑有很多瑕疵,但是可以很好的帮助理解Condition的使用,和生产者消费者模型。

Condition总结:

Condition采用通知机制,常用于生产者消费者模型中,解决生产者消费者速度匹配的问题。

使用方法:

使用Condition,必须先acquire,用完之后要release,因为内部使用了锁,默认使用RLock,最好的方法是使用with上下文管理。

生产者wait,会阻塞等待通知,被激活。

生产者生产好消息,对消费者发通知,可以使用notidy_all() 通知所有消费者或者notify()。

[Python 多线程] Condition (十)的更多相关文章

  1. [Python 多线程] asyncio (十六)

    asyncio 该模块是3.4版本加入的新功能. 先来看一个例子: def a(): for x in range(3): print('a.x', x) def b(): for x in 'abc ...

  2. Python 多线程 Condition 的使用

    Condition Condition(条件变量)通常与一个锁关联.需要在多个Contidion中共享一个锁时,可以传递一个Lock/RLock实例给构造方法,否则它将自己生成一个RLock实例. 可 ...

  3. python多线程--Condition(条件对象)

    Condition class threading.Condition(lock=None 这个类实现条件变量对象.条件变量允许一个或多个线程等待,知道它们被另一个线程唤醒. 如果给出了lock参数而 ...

  4. [Python 多线程] Concurrent (十五)

    concurrent包只有一个模块: concurrent.futures - 启动并行任务 异步并行任务编程模块,提供一个高级的异步可执行的便利接口. futures模块提供了2个池执行器 Thre ...

  5. 关于Python多线程condition变量的应用

    ''' 所谓条件变量,即这种机制是在满足了特定的条件后,线程才可以访问相关的数据. 它使用Condition类来完成,由于它也可以像锁机制那样用,所以它也有acquire方法和release方法,而且 ...

  6. 第十五章、Python多线程之信号量和GIL

    目录 第十五章.Python多线程之信号量和GIL 1. 信号量(Semaphore) 2. GIL 说明: 第十五章.Python多线程之信号量和GIL 1. 信号量(Semaphore) 信号量用 ...

  7. 第十五章、Python多线程同步锁,死锁和递归锁

    目录 第十五章.Python多线程同步锁,死锁和递归锁 1. 引子: 2.同步锁 3.死锁 引子: 4.递归锁RLock 原理: 不多说,放代码 总结: 5. 大总结 第十五章.Python多线程同步 ...

  8. Python 多线程、多进程 (二)之 多线程、同步、通信

    Python 多线程.多进程 (一)之 源码执行流程.GIL Python 多线程.多进程 (二)之 多线程.同步.通信 Python 多线程.多进程 (三)之 线程进程对比.多线程 一.python ...

  9. Python多线程多进程那些事儿看这篇就够了~~

    自己以前也写过多线程,发现都是零零碎碎,这篇写写详细点,填一下GIL和Python多线程多进程的坑~ 总结下GIL的坑和python多线程多进程分别应用场景(IO密集.计算密集)以及具体实现的代码模块 ...

随机推荐

  1. 使用重绘项美化WinForm中的控件

    如果你觉得项目中的ComboBox.ListBox或其它的Winforms控件不能满足你的显示要求,包括窗体在内很多控件都支持重绘修改显示样式.下面的示例完成对ComBox数据项的重绘,希望能起到抛砖 ...

  2. [PHP] 从 PHP 5.3.X 迁移到 PHP 5.6.X不兼容点

    从 PHP 5.3.X 迁移到 PHP 5.4.X不兼容点: 1.不再支持 安全模式 2.移除 魔术引号,设置 magic_quotes_gpc 系列将不会生效 3.Salsa10 和 Salsa20 ...

  3. 撩课-Web大前端每天5道面试题-Day7

    1. 你能描述一下渐进增强和优雅降级之间的不同吗? 定义: 优雅降级(graceful degradation): 一开始就构建站点的完整功能, 然后针对浏览器测试和修复 渐进增强(progressi ...

  4. C#学习笔记-原型模式

    题目:编写基本的简历. 实现: 创建基本的Resume类,然后主函数通过实例化Resume来写简历即可. Resume类: class Resume { private string name; pr ...

  5. Runtime 打开记事本

    package com.direct.str; import java.io.IOException; public class RunTimeDemo { /** * @param args */ ...

  6. sql:PostgreSQL9.3 Using RETURNS TABLE vs. OUT parameters

    http://www.postgresonline.com/journal/archives/201-Using-RETURNS-TABLE-vs.-OUT-parameters.html http: ...

  7. Freebsd10.3 Nginx多版本PHP

    服务器上需要使用多个php版本,费了好几天劲,终于有所收获.记录如下: 1.下载php-5.5.37.tar.bz2. 2.tar zvxf  php-5.5.37.tar.bz2 -C /usr/l ...

  8. PyCharm导入包的问题

    在此之前,我们说一下虚拟环境这个概念: 在django项目中,直接就安装各种package,可能会造成系统混乱,因为package之间会有依赖的.比方说,你现在直接装django,他会依赖其他的包(开 ...

  9. js中作用域链和作用域

    作用域 在JavaScript中,我们可以将作用域定义为一套规则,这套规则用来管理引擎如何在当前作用域以及嵌套的子作用域中根据标识符名称(变量名或者函数名)进行变量查找. 经过研究<高级程序设计 ...

  10. Mysql的命令

    学习mysql命令必须先安装哦:安装教程 1.doc连接Mysql 格式: mysql -h主机地址 -u用户名 -p用户密码 1.连接到本机上的MYSQL.首先打开DOS窗口,然后进入目录mysql ...