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中的Numeric包和Numarray包使用教程
Apr 13 Python
python中ASCII码字符与int之间的转换方法
Jul 09 Python
Python实现去除列表中重复元素的方法总结【7种方法】
Feb 16 Python
python抓取需要扫微信登陆页面
Apr 29 Python
Python OpenCV之图片缩放的实现(cv2.resize)
Jun 28 Python
python openCV获取人脸部分并存储功能
Aug 28 Python
python爬虫 线程池创建并获取文件代码实例
Sep 28 Python
sklearn+python:线性回归案例
Feb 24 Python
Anconda环境下Vscode安装Python的方法详解
Mar 29 Python
python针对Oracle常见查询操作实例分析
Apr 30 Python
python使用建议与技巧分享(二)
Aug 17 Python
Python threading模块condition原理及运行流程详解
Oct 05 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的伪随机数与真随机数详解
2015/05/27 PHP
php实现的Curl封装类Curl.class.php用法实例分析
2015/09/25 PHP
php文档工具PHP Documentor安装与使用方法
2016/01/25 PHP
PHPMailer使用QQ邮箱实现邮件发送功能
2017/08/18 PHP
js 关于=+与+=日期函数使用说明(赋值运算符)
2011/11/15 Javascript
利用try-catch判断变量是已声明未声明还是未赋值
2014/03/12 Javascript
jQuery实现手机号码输入提示功能实例
2015/04/30 Javascript
浅谈JavaScript中小数和大整数的精度丢失
2016/05/31 Javascript
全面解析JavaScript里的循环方法之forEach,for-in,for-of
2020/04/20 Javascript
js实现可键盘控制的简单抽奖程序
2016/07/13 Javascript
JavaScript使用键盘输入控制实现数字验证功能
2016/08/19 Javascript
ajax接收后台数据在html页面显示
2017/02/19 Javascript
vue组件如何被其他项目引用
2017/04/13 Javascript
基于jQuery实现的设置文本区域的光标位置
2018/06/15 jQuery
jQuery 淡入/淡出效果函数用法分析
2020/05/19 jQuery
微信小程序之导航滑块视图容器功能的实现代码(简单两步)
2020/06/19 Javascript
Python的装饰器用法学习笔记
2016/06/24 Python
Tensorflow之构建自己的图片数据集TFrecords的方法
2018/02/07 Python
Scrapy使用的基本流程与实例讲解
2018/10/21 Python
把pandas转换int型为str型的方法
2019/01/29 Python
Python编写通讯录通过数据库存储实现模糊查询功能
2019/07/18 Python
Pandas对每个分组应用apply函数的实现
2020/12/13 Python
巴黎一票通:The Paris Pass
2018/02/10 全球购物
装饰活动策划方案
2014/02/11 职场文书
酒店总经理助理职责
2014/02/12 职场文书
婚假请假条格式及范文
2014/04/10 职场文书
给校长的建议书400字
2014/05/15 职场文书
文员试用期转正自我鉴定
2014/09/14 职场文书
干部作风整顿个人剖析材料
2014/10/06 职场文书
致百米运动员广播稿5篇
2014/10/13 职场文书
责任书范本大全
2015/05/11 职场文书
幼儿园辞职信
2015/05/13 职场文书
一起来学习Python的元组和列表
2022/03/13 Python
css3应用示例:新增的选择器
2022/03/16 HTML / CSS
如何使用python包中的sched事件调度器
2022/04/30 Python
zabbix如何添加监控主机和自定义监控项
2022/08/14 Servers