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实现远程调用MetaSploit的方法
Aug 22 Python
Python函数中定义参数的四种方式
Nov 30 Python
Python中的localtime()方法使用详解
May 22 Python
利用Python开发微信支付的注意事项
Aug 19 Python
python解决Fedora解压zip时中文乱码的方法
Sep 18 Python
Python 一句话生成字母表的方法
Jan 02 Python
python使用threading.Condition交替打印两个字符
May 07 Python
python3使用print打印带颜色的字符串代码实例
Aug 22 Python
python opencv根据颜色进行目标检测的方法示例
Jan 15 Python
Python基于paramunittest模块实现excl参数化
Apr 26 Python
python实现股票历史数据可视化分析案例
Jun 10 Python
Python与C++中梯度方向直方图的实现
Mar 17 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相当简单的分页类
2008/10/02 PHP
PHP 获取MSN好友列表的代码(2009-05-14测试通过)
2009/09/09 PHP
PHP+JS+rsa数据加密传输实现代码
2011/03/23 PHP
你可能不知道PHP get_meta_tags()函数
2014/05/12 PHP
Yii2 hasOne(), hasMany() 实现三表关联的方法(两种)
2017/02/15 PHP
Yii框架实现多数据库配置和操作的方法
2017/05/25 PHP
PHP观察者模式原理与简单实现方法示例
2017/08/25 PHP
TP5.0框架实现无限极回复功能的方法分析
2019/05/04 PHP
Prototype源码浅析 Number部分
2012/01/16 Javascript
javascript中全局对象的parseInt()方法使用介绍
2013/12/19 Javascript
jQuery处理图片加载失败的常用方法
2015/06/08 Javascript
跟我学习javascript创建对象(类)的8种方法
2015/11/20 Javascript
JS失效 提示HTML1114: (UNICODE 字节顺序标记)的代码页 utf-8 覆盖(META 标记)的冲突的代码页 utf-8
2017/06/23 Javascript
微信小程序tabBar用法实例详解
2017/12/04 Javascript
react-native封装插件swiper的使用方法
2018/03/20 Javascript
npm的lock机制解析
2019/06/20 Javascript
vue3实现v-model原理详解
2019/10/09 Javascript
vue点击按钮动态创建与删除组件功能
2019/12/29 Javascript
解决Vue 给mapState中定义的属性赋值报错的问题
2020/06/22 Javascript
python模块之re正则表达式详解
2017/02/03 Python
python django model联合主键的例子
2019/08/06 Python
python如何删除文件、目录
2020/06/23 Python
python自动化测试三部曲之request+django实现接口测试
2020/10/07 Python
如何实现一个python函数装饰器(Decorator)
2020/10/12 Python
编写python代码实现简单抽奖器
2020/10/20 Python
高性能装备提升营地:Kammok
2019/02/27 全球购物
strstr()的简单实现
2013/09/26 面试题
努力学习演讲稿
2014/05/10 职场文书
公司承诺书范文
2014/05/19 职场文书
小学中等生评语
2014/12/29 职场文书
财务人员个人工作总结
2015/02/27 职场文书
个人年终总结开头
2015/03/06 职场文书
幼儿园班级管理心得体会
2016/01/07 职场文书
导游词之岳阳楼
2019/09/25 职场文书
关于Vue中的options选项
2022/03/22 Vue.js
SQL Server使用PIVOT与unPIVOT实现行列转换
2022/05/25 SQL Server