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练习程序批量修改文件名
Jan 16 Python
使用Python编写基于DHT协议的BT资源爬虫
Mar 19 Python
django缓存配置的几种方法详解
Jul 16 Python
对python中的高效迭代器函数详解
Oct 18 Python
浅谈Python 列表字典赋值的陷阱
Jan 20 Python
将python文件打包成EXE应用程序的方法
May 22 Python
python提取log文件内容并画出图表
Jul 08 Python
Pyecharts绘制全球流向图的示例代码
Jan 08 Python
django admin后管定制-显示字段的实例
Mar 11 Python
Python xlrd模块导入过程及常用操作
Jun 10 Python
Python3爬虫中关于Ajax分析方法的总结
Jul 10 Python
python 监控服务器是否有人远程登录(详细思路+代码)
Dec 18 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打开远程文件的方法和风险及解决方法
2013/11/12 PHP
Yii2下session跨域名共存的解决方案
2017/02/04 PHP
浅析PHP中的闭包和匿名函数
2017/12/25 PHP
PHP调用微博接口实现微博登录的方法示例
2018/09/22 PHP
通过javascript获取iframe里的值示例代码
2013/06/24 Javascript
jquery中的$(document).ready()使用小结
2014/02/14 Javascript
JavaScript用JQuery呼叫Server端方法示例代码
2014/09/03 Javascript
JavaScript获取伪元素(Pseudo-Element)属性的方法技巧
2015/03/13 Javascript
充分发挥Node.js程序性能的一些方法介绍
2015/06/23 Javascript
jquery获得当前html页面源码的方法
2015/07/14 Javascript
深入分析jsonp协议原理
2015/09/26 Javascript
jQuery+Ajax实现无刷新分页
2015/10/30 Javascript
TypeScript Type Innference(类型判断)
2016/03/10 Javascript
AngularJS实践之使用NgModelController进行数据绑定
2016/10/08 Javascript
详解plotly.js 绘图库入门使用教程
2018/02/23 Javascript
在vue项目中使用sass语法问题
2019/07/18 Javascript
前端vue+elementUI如何实现记住密码功能
2020/09/20 Javascript
uni-app 自定义底部导航栏的实现
2020/12/11 Javascript
Flask框架的学习指南之制作简单blog系统
2016/11/20 Python
使用 Python 实现微信公众号粉丝迁移流程
2018/01/03 Python
python使用tomorrow实现多线程的例子
2019/07/20 Python
Django处理Ajax发送的Get请求代码详解
2019/07/29 Python
django迁移文件migrations的实现
2020/03/31 Python
Django 实现图片上传和下载功能
2020/12/31 Python
草莓网美国官网:Strawberrynet USA
2016/12/11 全球购物
花园仓库建筑:Garden Buildings Direct
2018/02/16 全球购物
Fossil加拿大官网:化石手表、手袋、首饰及配饰
2019/04/23 全球购物
渗透攻击的测试步骤
2014/06/07 面试题
厨房工作人员岗位职责
2013/11/15 职场文书
法人授权委托书范本
2014/04/04 职场文书
幼儿园安全责任书范本
2014/07/24 职场文书
纪律教育学习月活动总结
2014/08/27 职场文书
2015学校图书管理员工作总结
2015/05/11 职场文书
2016年乡镇七一建党节活动总结
2016/04/05 职场文书
css中z-index: 0和z-index: auto的区别
2021/08/23 HTML / CSS
MongoDB数据库部署环境准备及使用介绍
2022/03/21 MongoDB