Python多线程编程(七):使用Condition实现复杂同步


Posted in Python onApril 05, 2015

目前我们已经会使用Lock去对公共资源进行互斥访问了,也探讨了同一线程可以使用RLock去重入锁,但是尽管如此我们只不过才处理了一些程序中简单的同步现象,我们甚至还不能很合理的去解决使用Lock锁带来的死锁问题。所以我们得学会使用更深层的解决同步问题。

Python提供的Condition对象提供了对复杂线程同步问题的支持。Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法。

使用Condition的主要方式为:线程首先acquire一个条件变量,然后判断一些条件。如果条件不满足则wait;如果条件满足,进行一些处理改变条件后,通过notify方法通知其他线程,其他处于wait状态的线程接到通知后会重新判断条件。不断的重复这一过程,从而解决复杂的同步问题。

下面我们通过很著名的“生产者-消费者”模型来来演示下,在Python中使用Condition实现复杂同步。

''' 

Created on 2012-9-8 

 

@author: walfred 

@module: thread.TreadTest7 

'''  

 

import threading  

import time  

 

condition = threading.Condition()  

products = 0  

 

class Producer(threading.Thread):  

    def __init__(self):  

        threading.Thread.__init__(self)  

 

    def run(self):  

        global condition, products  

        while True:  

            if condition.acquire():  

                if products < 10:  

                    products += 1;  

                    print "Producer(%s):deliver one, now products:%s" %(self.name, products)  

                    condition.notify()  

                else:  

                    print "Producer(%s):already 10, stop deliver, now products:%s" %(self.name, products)  

                    condition.wait();  

                condition.release()  

                time.sleep(2)  

 

class Consumer(threading.Thread):  

    def __init__(self):  

        threading.Thread.__init__(self)  

 

    def run(self):  

        global condition, products  

        while True:  

            if condition.acquire():  

                if products > 1:  

                    products -= 1  

                    print "Consumer(%s):consume one, now products:%s" %(self.name, products)  

                    condition.notify()  

                else:  

                    print "Consumer(%s):only 1, stop consume, products:%s" %(self.name, products)  

                    condition.wait();  

                condition.release()  

                time.sleep(2)  

 

if __name__ == "__main__":  

    for p in range(0, 2):  

        p = Producer()  

        p.start()  

 

    for c in range(0, 10):  

        c = Consumer()  

        c.start()

代码中主要实现了生产者和消费者线程,双方将会围绕products来产生同步问题,首先是2个生成者生产products ,而接下来的10个消费者将会消耗products,代码运行如下:

Producer(Thread-1):deliver one, now products:1

Producer(Thread-2):deliver one, now products:2

Consumer(Thread-3):consume one, now products:1

Consumer(Thread-4):only 1, stop consume, products:1

Consumer(Thread-5):only 1, stop consume, products:1

Consumer(Thread-6):only 1, stop consume, products:1

Consumer(Thread-7):only 1, stop consume, products:1

Consumer(Thread-8):only 1, stop consume, products:1

Consumer(Thread-10):only 1, stop consume, products:1

Consumer(Thread-9):only 1, stop consume, products:1

Consumer(Thread-12):only 1, stop consume, products:1

Consumer(Thread-11):only 1, stop consume, products:1

另外:Condition对象的构造函数可以接受一个Lock/RLock对象作为参数,如果没有指定,则Condition对象会在内部自行创建一个RLock;除了notify方法外,Condition对象还提供了notifyAll方法,可以通知waiting池中的所有线程尝试acquire内部锁。由于上述机制,处于waiting状态的线程只能通过notify方法唤醒,所以notifyAll的作用在于防止有线程永远处于沉默状态。
Python 相关文章推荐
python下函数参数的传递(参数带星号的说明)
Sep 19 Python
Django与遗留的数据库整合的方法指南
Jul 24 Python
Python爬虫代理IP池实现方法
Jan 05 Python
老生常谈Python序列化和反序列化
Jun 28 Python
TensorFlow实现简单卷积神经网络
May 24 Python
python变量赋值方法(可变与不可变)
Jan 12 Python
详解python解压压缩包的五种方法
Jul 05 Python
将python运行结果保存至本地文件中的示例讲解
Jul 11 Python
如何使用Flask-Migrate拓展数据库表结构
Jul 24 Python
15行Python代码实现免费发送手机短信推送消息功能
Feb 27 Python
Jupyter Notebook打开任意文件夹操作
Apr 14 Python
Python+Selenium实现自动化的环境搭建的步骤(图文)
Sep 01 Python
Python多线程编程(六):可重入锁RLock
Apr 05 #Python
Python多线程编程(五):死锁的形成
Apr 05 #Python
Python多线程编程(四):使用Lock互斥锁
Apr 05 #Python
Python多线程编程(三):threading.Thread类的重要函数和方法
Apr 05 #Python
Python多线程编程(二):启动线程的两种方法
Apr 05 #Python
Python多线程编程(一):threading模块综述
Apr 05 #Python
Python中使用dom模块生成XML文件示例
Apr 05 #Python
You might like
PHP中copy on write写时复制机制介绍
2014/05/13 PHP
ThinkPHP查询中的魔术方法简述
2014/06/25 PHP
在openSUSE42.1下编译安装PHP7 的方法
2015/12/24 PHP
Laravel5.7 数据库操作迁移的实现方法
2019/04/12 PHP
JavaScript Event学习补遗 addEventSimple
2010/02/11 Javascript
JS获取鼠标坐标的实例方法
2013/07/18 Javascript
js获取客户端外网ip的简单实例
2013/11/21 Javascript
用jquery等比例控制图片宽高的具体实现
2014/01/28 Javascript
HTML页面弹出居中可拖拽的自定义窗口层
2014/05/07 Javascript
浅析Node.js查找字符串功能
2014/09/03 Javascript
jQuery实现拖动调整表格单元格大小的代码实例
2015/01/13 Javascript
js实现按钮控制图片360度翻转特效的方法
2015/02/17 Javascript
详解JavaScript基本类型和引用类型
2015/12/09 Javascript
全面解析Bootstrap中Carousel轮播的使用方法
2016/06/13 Javascript
AngularJS表单和输入验证实例
2016/11/02 Javascript
浅谈jquery选择器 :first与:first-child的区别
2016/11/20 Javascript
JavaScript 动态三角函数实例详解
2017/01/08 Javascript
JavaScript拖动层Div代码
2017/03/01 Javascript
基于D3.js实现时钟效果
2018/07/17 Javascript
微信小程序Getuserinfo解决方案图解
2018/08/24 Javascript
微信小程序调用微信支付接口的实现方法
2019/04/29 Javascript
浅谈Vue为什么不能检测数组变动
2019/10/14 Javascript
JavaScript ES6 Class类实现原理详解
2020/05/08 Javascript
解决vue项目input输入框双向绑定数据不实时生效问题
2020/08/05 Javascript
[01:23:59]2018DOTA2亚洲邀请赛 4.1 小组赛 B组 VP vs Secret
2018/04/03 DOTA
Python中统计函数运行耗时的方法
2015/05/05 Python
基于python实现的抓取腾讯视频所有电影的爬虫
2016/04/22 Python
python traceback捕获并打印异常的方法
2018/08/31 Python
Python列表的切片实例讲解
2019/08/20 Python
python3实现elasticsearch批量更新数据
2019/12/03 Python
如何通过python计算圆周率PI
2020/11/11 Python
波兰数码相机及配件网上商店: Cyfrowe.pl
2017/06/19 全球购物
华为python面试题
2016/05/03 面试题
出国签证在职证明
2014/01/16 职场文书
小学生2014国庆节演讲稿:祖国在我心中
2014/09/21 职场文书
2015年小学体育工作总结
2015/05/22 职场文书