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 查找文件夹下所有文件 实现代码
Jul 01 Python
python生成随机验证码(中文验证码)示例
Apr 03 Python
使用Python读写文本文件及编写简单的文本编辑器
Mar 11 Python
python递归查询菜单并转换成json实例
Mar 27 Python
python实现闹钟定时播放音乐功能
Jan 25 Python
Python实现线程状态监测简单示例
Mar 28 Python
使用pandas对两个dataframe进行join的实例
Jun 08 Python
Python函数中不定长参数的写法
Feb 13 Python
python如何使用jt400.jar包代码实例
Dec 20 Python
基于TensorFlow常量、序列以及随机值生成实例
Jan 04 Python
python下载卫星云图合成gif的方法示例
Feb 18 Python
Python Tkinter图形工具使用方法及实例解析
Jun 15 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笔记之常用文件操作
2010/10/12 PHP
session在PHP大型web应用中的使用
2011/06/25 PHP
php文字水印和php图片水印实现代码(二种加水印方法)
2013/12/25 PHP
php使用array_search函数实现数组查找的方法
2015/06/12 PHP
简单谈谈PHP中的include、include_once、require以及require_once语句
2016/04/23 PHP
掌握PHP垃圾回收机制详解
2019/03/13 PHP
prototype Element学习笔记(篇一)
2008/10/26 Javascript
javascript客户端解决方案 缓存提供程序
2010/07/14 Javascript
基于jquery的跨域调用文件
2010/11/19 Javascript
给应用部分的js代码设定一个统一的入口
2014/06/15 Javascript
node.js中的events.emitter.once方法使用说明
2014/12/10 Javascript
jQuery禁用快捷键例如禁用F5刷新 禁用右键菜单等的简单实现
2016/08/31 Javascript
JavaScript正则表达式exec/g实现多次循环用法示例
2017/01/17 Javascript
浅谈JS中的常用选择器及属性、方法的调用
2017/07/28 Javascript
浅谈React深度编程之受控组件与非受控组件
2017/12/26 Javascript
JavaScript实现一个带AI的井字棋游戏源码
2018/05/21 Javascript
详解vue中组件参数
2018/07/09 Javascript
Vuex 模块化使用详解
2019/07/31 Javascript
nodejs使用Sequelize框架操作数据库的实现
2020/10/21 NodeJs
JavaScript中的Proxy对象
2020/11/27 Javascript
[00:33]2018DOTA2亚洲邀请赛TNC出场
2018/04/04 DOTA
Python实现读写sqlite3数据库并将统计数据写入Excel的方法示例
2017/08/07 Python
分享6个隐藏的python功能
2017/12/07 Python
python 把文件中的每一行以数组的元素放入数组中的方法
2018/04/29 Python
python 统计一个列表当中的每一个元素出现了多少次的方法
2018/11/14 Python
Django model 中设置联合约束和联合索引的方法
2019/08/06 Python
pytorch torch.expand和torch.repeat的区别详解
2019/11/05 Python
Python关于__name__属性的含义和作用详解
2020/02/19 Python
Pytorch实现WGAN用于动漫头像生成
2021/03/04 Python
使用CSS3中的calc()属性来以算式表达尺寸数值
2016/06/06 HTML / CSS
优瑞自动咖啡机官网:Jura
2018/09/29 全球购物
斯图尔特·韦茨曼鞋加拿大官网:Stuart Weitzman加拿大
2019/10/13 全球购物
党风廉政建设责任书
2014/04/14 职场文书
暂住证证明
2015/06/19 职场文书
Redis字典实现、Hash键冲突及渐进式rehash详解
2021/09/04 Redis
使用Nginx的访问日志统计PV与UV
2022/05/06 Servers