python多线程生产者消费者_【Python爬虫学习笔记10】多线程中的生产者消费者模式...

本文介绍了在Python中使用threading模块的Lock和Condition类实现生产者消费者模式。生产者线程负责向金库存钱,消费者线程负责取钱,金库余额由全局变量维护。Lock类通过加锁和释放锁确保数据一致性,Condition类则允许线程在条件不满足时自动等待,提高程序效率。示例代码展示了两种实现方式的细节和工作流程。
摘要由CSDN通过智能技术生成

在多线程编程中,最经典的模式是生产者消费者模式。其中,生产者是专门用来生产数据的线程,它把数据存放在一个中间变量中;而消费者则从这个中间变量取出数据进行消费。由于生产者和消费者共享中间变量,这些变量大多是全局的,因此需要使用锁来保证数据完整性,防止多线程共享问题的产生。

Python threading模块为我们提供了两种实现生产者消费者模式的方案,分别基于Lock类和Condition类。在具体介绍前,我们先来说明一下我们的生产者消费者模型背景:我们这里有一个金库gMoney,若干个生产者Producer和消费者Consumer,其中生产者负责向金库里存钱,而消费者则从金库中取钱;当生产者存放10次钱以后则不再存钱,而消费者所取的钱只要没有超过金库剩余便可一直取。

接下来我们我们对两种方案的实现进行介绍。

使用Lock类实现

Lock类实现方案采用的是threading中的锁机制,通过对共享变量操作加锁和释放锁来确保数据的统一性,具体程序如下:

## 使用Lock类实现生产者消费者模式

importthreadingimportrandom,timegMoney= 1000 #定义全局金库、

gLock = threading.Lock() #实例化对金库操作的锁

gTotaltimes = 10 #存钱总次数和

gTimes = 0 #存钱当前次数

#生产者线程类

classProducer(threading.Thread):defrun(self):globalgMoney, gTimeswhile True: #循环存钱操作

if gTimes >= gTotaltimes: return #当存钱次数上限时结束线程

money = random.randint(100, 1000) #存钱数

gLock.acquire() #对金库操作加锁

gMoney +=moneyprint('%s produces $%s,the balance is %s .' %(threading.current_thread(), money, gMoney))

gTimes+= 1gLock.release()#对金库操作释放锁

time.sleep(0.5)#消费者线程类

classConsumer(threading.Thread):defrun(self):globalgMoneywhile True: #循环取钱操作

money = random.randint(100, 1000) #取钱数

if gMoney >= money: #金库钱充足

gLock.acquire() #对金库操作加锁

gMoney -=moneyprint('%s consumes $%s,the balance is %s .' %(threading.current_thread(), money, gMoney))

gLock.release()#对金库操作释放锁

time.sleep(0.5)else: #金库钱不足

if gTimes >= gTotaltimes: #若已达存钱次数上限,则退出

return

print('%s wants to consume $%s,while the balance is %s .' %(threading.current_thread(), money, gMoney))#开启两个生产者线程和1个消费者线程

defmain():for x in range(2):

t=Producer()

t.start()for x in range(1):

t=Consumer()

t.start()if __name__ == '__main__':

main()

使用Condition类实现

在threading模块中的另一个较优的解决方案是使用Condition类,其可以在没有数据的时候自动地处于阻塞等待状态,而一旦有合适的数据则可以使用notify相关函数来通知处于等待状态的线程(此时并不会使其直接执行)。这样一来就可以不用做一些无用的上锁和解锁操作,提高程序的性能。

在实现生产者消费者模式前,先来说明一下Condition类的几个常用方法:

1.acquire():上锁。

2.release():释放锁。

3.wait():将当前线程处于等待状态,并且会自动释放其已占有的锁。该线程可以被其他线程使用notify()和notify_all()唤醒,被唤醒后会继续自动等待上锁,上锁后再执行后续代码。

4.notify()/notify_all():通知某个/所有正在等待的线程。这两个方法都不会释放锁,并且需要在release()之前调用。

和Lock方案类似,仅做了少数地方的修改,具体实现如下:

## 使用Condition类实现生产者消费者模式

importthreadingimportrandom, time

gMoney= 1000gCondition= threading.Condition() #实例化Condition类

gTotalTimes = 10gTimes=0#生产者线程类

classProducer(threading.Thread):defrun(self):globalgMoney, gTimeswhileTrue:if gTimes >= gTotalTimes: returnmoney= random.randint(100, 1000)

gCondition.acquire()#加锁

gMoney +=moneyprint('%s produces $%s,the balance is %s .' %(threading.current_thread(), money, gMoney))

gTimes+= 1gCondition.release()#释放锁

time.sleep(0.5)#消费者线程类

classConsumer(threading.Thread):defrun(self):globalgMoneywhileTrue:

money= random.randint(100, 1000)

gCondition.acquire()#加锁

while gMoney < money: #金库不足

if gTimes >=gTotalTimes:

gCondition.release()#如果达到存钱次数上限则释放锁并退出

return

print('%s wants to consume $%s,while the balance is %s .' %(threading.current_thread(), money, gMoney))

gCondition.wait()#不足情况下进入等待

gMoney -=moneyprint('%s consumes $%s,the balance is %s .' %(threading.current_thread(), money, gMoney))

gCondition.release()#释放锁

time.sleep(0.5)#开启线程

defmain():for x in range(2):

t=Producer()

t.start()for x in range(1):

t=Consumer()

t.start()if __name__ == '__main__':

main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值