Python使用Condition对象实现多线程同步

使用Condition对象可以在某些事件触发后才处理数据或执行特定的功能代码,可以用于不同线程之间的通信或通知,以实现更高级别的同步。在内部实现上,Condition对象总是与某种锁对象相关联。

Condition对象除了具有acquire()和release()方法之外,还有wait()、wait_for()、notify()、notify_all()等方法:

  • wait(timeout=None)方法会释放锁,并阻塞当前线程直到超时或其他线程针对同一个Condition对象调用了notify()/notify_all()方法,被唤醒之后当前线程会重新尝试获取锁并在成功获取锁之后结束wait()方法,然后继续执行;
  • wait_for(predicate, timeout=None)方法阻塞当前线程直到超时或者指定条件得到满足;
  • notify(n=1)唤醒等待该Condition对象的一个或多个线程,该方法并不负责释放锁;
  • notify_all()方法会唤醒等待该Condition对象的所有线程。

本文代码模拟了经典的生产者-消费者问题,使用列表模拟物品池,生产者往里放物品,消费者从中获取物品,物品池满时生产者等待,空时消费者等待。

import threading

from random import randint

from time import sleep

#自定义生产者线程类

class Producer(threading.Thread):

def __init__(self, threadname):

threading.Thread.__init__(self,name=threadname)

def run(self):

global x

while True:

sleep(1)

#获取锁

con.acquire()

#假设共享列表中最多能容纳5个元素

if len(x) == 5:

#如果共享列表已满,生产者等待

print('Producer is waiting.....')

con.wait()

else:

r = randint(1, 1000)

print('Produced:', r)

#产生新元素,添加至共享列表

x.append(r)

#唤醒等待条件的线程

con.notify()

#释放锁

con.release()

#自定义消费者线程类

class Consumer(threading.Thread):

def __init__(self, threadname):

threading.Thread.__init__(self, name =threadname)

def run(self):

global x

while True:

sleep(2)

#获取锁

con.acquire()

if not x:

#等待

print('Consumer is waiting.....')

con.wait()

else:

print('Consumed:', x.pop(0))

con.notify()

con.release()

#创建Condition对象以及生产者线程和消费者线程

con = threading.Condition()

x = []

Producer('Producer').start()

Consumer('Consumer').start()

某次运行部分结果如下

Produced: 696

Produced: 970

Consumed: 696

Produced: 546

Produced: 30

Consumed: 970

Produced: 824

Produced: 68

Consumed: 546

Produced: 409

Produced: 172

Consumed: 30

Produced: 820

Producer is waiting.....

Consumed: 824

Produced: 2

Producer is waiting.....

Consumed: 68

Produced: 473

Producer is waiting.....

Consumed: 409

Produced: 167

Consumed: 172

Produced: 192

Producer is waiting.....

Consumed: 820

Produced: 789

Consumed: 2

Produced: 855

Producer is waiting.....

Consumed: 473

Produced: 754

Producer is waiting.....

Consumed: 167

Produced: 549

Consumed: 192

Produced: 100

Producer is waiting.....

Consumed: 789

Produced: 862

Consumed: 855

Produced: 537

Producer is waiting.....

Consumed: 754

Produced: 715

Consumed: 549

Produced: 79

Producer is waiting.....

Consumed: 100

Produced: 445

Consumed: 862

Produced: 64

Producer is waiting.....

Consumed: 537

Produced: 755

Consumed: 715

Produced: 8

^C(按Crtl+Break退出)

原文发布于微信公众号 - Python小屋(Python_xiaowu)

原文发表时间:2017-05-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大闲人柴毛毛

三分钟掌握“职责链模式”——轻松搞定设计模式

职责链模式的官方定义: 职责链模式使得多个对象都有机会处理请求,从而降低了请求的发送者和接受者之间的耦合关系。这些对象被连成一条链,并沿着这条链传递发送者的请求...

37112
来自专栏腾讯数据库技术

Linux删除文件过程解析

9432
来自专栏雪胖纸的玩蛇日常

Vue+Django2.0 REST framework 打造前后端分离的生鲜电商项目(五)商品列表页

9806
来自专栏JackieZheng

RabbitMQ入门-从HelloWorld开始

从读者的反馈谈RabbitMQ 昨天发完《RabbitMQ入门-初识RabbitMQ》,我陆陆续续收到一些反馈。鉴于部分读者希望结合实例来讲 期待下篇详细,最好...

2325
来自专栏斑斓

Redux框架reducer对状态的处理

前言 在react+redux项目里,关于reducer处理state的方式,在redux官方文档中有这样一段描述: 不要修改 state。 使用 Objec...

3745
来自专栏ChaMd5安全团队

360春秋杯3道web题的简单分析

360春秋杯3道web题的简单分析 From ChaMd5安全团队核心成员 pcat&香香 where is my cat 这题一开始很坑的,存在着/.git/...

4668
来自专栏salesforce零基础学习

salesforce 零基础开发入门学习(八)数据分页简单制作

本篇介绍通过使用VF自带标签和Apex实现简单的数据翻页功能。 代码上来之前首先简单介绍一下本篇用到的主要知识: 1.ApexPages命名空间 此命名空间下的...

2478
来自专栏Golang语言社区

Golang工程经验(上)

作为一个C/C++的开发者而言,开启Golang语言开发之路是很容易的,从语法、语义上的理解到工程开发,都能够快速熟悉起来;相比C、C++,Golang语言更简...

6242
来自专栏上善若水

S009SEAndroid中定义的各种策略文件

在external/sepolicy目录 存放了很多SELinux的策略定义文件,在类似device/lge/mako/sepolicy目录下也放了策略文件,作...

1965
来自专栏JackieZheng

RabbitMQ入门-从HelloWorld开始

从读者的反馈谈RabbitMQ 昨天发完《RabbitMQ入门-初识RabbitMQ》,我陆陆续续收到一些反馈。鉴于部分读者希望结合实例来讲 期待下篇详细,最好...

2139

扫码关注云+社区

领取腾讯云代金券