多线程之Condition
我们这说Condition,多线程编程中使用Condition对象代替lock, 能够实现在某个事件触发后才处理数据。
Condition版的生产者与消费者模式:
Lock版本的生产者与消费者模式可以正常的运行。但是存在一个不足,在消费者中,总是通过while True死循环并且上锁的方式去判断钱够不够。上锁是一个很耗费CPU资源的行为。
因此这种方式不是最好的。还有一种更好的方式便是使用threading.condition 来实现。threading.Condition 可以在没有数据的时候处于阻塞等待状态。一旦有合适的数据了,还可以使用notify相关的函数来通知其他处于等待状态的线程。
这样就可以不用做一些无用的上锁和解锁的操作。可以提高程序的性能。首先对threading.Condition 相关的函数做个介绍,threading.Condition 类侧threading.Lock,可以在修改全局数据的时候进行上锁,也可以在修改完毕后进行解锁。
以下将一些常用的函数做个简单的介绍:
1.acquire:上锁。
2.release:解锁。
3.wait:将当前线程处于等待状态,并且会释放锁。可以被其他线程使用notify和notify_all函数唤醒。被唤醒后会继续等待上锁,上锁后继续执行下面的代码。
4.notify:通知某个正在等待的线程,默认是第1个等待的线程。
5.notify-o11:通知所有正在等待的线程。notify和notify-o11不会释放锁。并且需要在release之前调用。
Condition 版的生产者与消费者模式代码如下:
import threading
import random
import time
gMoney=1000
gCondition = threading.Condition() #等同于threading.Lock
gTimes = 0
gTotalTimes = 5
class Producer(threading.Thread):
def run(self):
global gMoney
global gCondition
global gTimes
while True:
money=random.randint(100,1000)
gCondition.acquire() #加锁(全局变量改变前(gMoney))
if gTimes>=gTotalTimes:
gCondition.release() #解锁
print("当前生产者总共生产了%s次" %gTimes)
break
gMoney += money
print("%s当前存入%s元钱,剩余%s元线" %(threading.current_thread(),money,gMoney))
gTimes+=1
gCondition.notify_all() #通知正在等待的线程(wait)
gCondition.release()
time.sleep(0.5)
class Cosumer(threading.Thread):
def run(self):
global gMoney
while True:
money = random.randint(100,1000)
gCondition.acquire()
while gMoney < money:
if gTimes >= gTotalTimes:
gCondition.release()
return
print("%s准备消费%d元钱,剩余%d元钱,不足" %(threading.current_thread(),money,gMoney))
gCondition.wait() #等待状态 (获取锁) 直到生产者把钱加上 (有钱了再去排队消费)
gMoney -= money
print("%s消费了%d元钱,剩余%d元钱" %(threading.current_thread(),money,gMoney))
gCondition.release()
time.sleep(0.5)
def main():
for x in range(3):
t = Cosumer(name="消费者线程%s" %x)
t.start()
for y in range(5):
t1 = Producer(name="生产者线程%s" %y)
t1.start()
if __name__ == '__main__':
main()