Event是一种非常简单的线程通信机制,一个线程发出一个 Event,另一个线程可通过该 Event 被触发。

Event 本身管理一个内部旗标,程序可以通过 Event 的 set() 方法将该旗标设置为 True,也可以调用 clear() 方法将该旗标设置为 False。程序可以调用 wait() 方法来阻塞当前线程,直到 Event 的内部旗标被设置为 True。

Event 提供了如下方法:

is_set():该方法返回 Event 的内部旗标是否为True。

set():该方法将会把 Event 的内部旗标设置为 True,并唤醒所有处于等待状态的线程。

clear():该方法将 Event 的内部旗标设置为 False,通常接下来会调用 wait() 方法来阻塞当前线程。

wait(timeout=None):该方法会阻塞当前线程。

下面程序示范了 Event 最简单的用法:

import threading

import time

event = threading.Event()

def cal(name):

# 等待事件,进入等待阻塞状态

print('%s 启动' % threading.currentThread().getName())

print('%s 准备开始计算状态' % name)

event.wait() # ①

# 收到事件后进入运行状态

print('%s 收到通知了.' % threading.currentThread().getName())

print('%s 正式开始计算!'% name)

# 创建并启动两条,它们都会①号代码处等待

threading.Thread(target=cal, args=('甲', )).start()

threading.Thread(target=cal, args=("乙", )).start()

time.sleep(2) #②

print('------------------')

# 发出事件

print('主线程发出事件')

event.set()

上面程序以 cal() 函数为 target,创建并启动了两个线程。由于 cal() 函数在 ① 号代码处调用了 Event 的 wait(),因此两个线程执行到 ① 号代码处都会进入阻塞状态;即使主线程在 ② 号代码处被阻塞,两个子线程也不会向下执行。

直到主程序执行到最后一行,程序调用了 Event 的 set() 方法将 Event 的内部旗标设直为 True,并唤醒所有等待的线程,这两个线程才能向下执行。

运行上面程序,将看到如下输出结果:

Thread-1 启动

甲 准备开始计算状态

Thread-2 启动

乙 准备开始计算状态

------------------

主线程发出事件

Thread-1 收到通知了.

Thread-2 收到通知了.

甲 正式开始计算!

乙 正式开始计算!

上面程序还没有使用 Event 的内部旗标,如果结合 Event 的内部旗标,同样可实现前面的 Account 的生产者-消费者效果:存钱线程(生产者)存钱之后,必须等取钱线程(消费者)取钱之后才能继续向下执行。

Event 实际上优点类似于 Condition 和旗标的结合体,但 Event 本身并不带 Lock 对象,因此如果要实现线程同步,还需要额外的 Lock 对象。

下面是使用 Event 改写后的 Account:

import threading

class Account:

# 定义构造器

def __init__(self, account_no, balance):

# 封装账户编号、账户余额的两个成员变量

self.account_no = account_no

self._balance = balance

self.lock = threading.Lock()

self.event = threading.Event()

# 因为账户余额不允许随便修改,所以只为self._balance提供getter方法

def getBalance(self):

return self._balance

# 提供一个线程安全的draw()方法来完成取钱操作

def draw(self, draw_amount):

# 加锁

self.lock.acquire()

# 如果Event内部旗标为True,表明账户中已有人存钱进去

if self.event.is_set():

# 执行取钱操作

print(threading.current_thread().name

+ " 取钱:" + str(draw_amount))

self._balance -= draw_amount

print("账户余额为:" + str(self._balance))

# 将Event内部旗标设为False

self.event.clear()

# 释放加锁

self.lock.release()

# 阻塞当前线程阻塞

self.event.wait()

else:

# 释放加锁

self.lock.release()

# 阻塞当前线程阻塞

self.event.wait()

def deposit(self, deposit_amount):

# 加锁

self.lock.acquire()

# 如果Event内部旗标为False,表明账户中还没有人存钱进去

if not self.event.is_set():

# 执行存款操作

print(threading.current_thread().name\

+ " 存款:" + str(deposit_amount))

self._balance += deposit_amount

print("账户余额为:" + str(self._balance))

# 将Event内部旗标设为True

self.event.set()

# 释放加锁

self.lock.release()

# 阻塞当前线程阻塞

self.event.wait()

else:

# 释放加锁

self.lock.release()

# 阻塞当前线程阻塞

self.event.wait()

python中event_Python Event实现线程通信相关推荐

  1. python 强制结束线程_在python中实现强制关闭线程的示例

    Python 如何强制关闭线程过去只可以用来回忆,别沉迷在阴影中,否则永远看不清前面的路. Python用sleep停止一个线程的运行,而不影响主线程的运行,案例代码如下: from threadin ...

  2. java 线程 condition_Java编程中实现Condition控制线程通信

    java中控制线程通信的方法 1.传统的方式:利用synchronized关键字来保证同步,结合wait(),notify(),notifyall()控制线程通信.不灵活. 2.利用condition ...

  3. python 异步 生产者 消费者_python 线程通信 生产者与消费者

    1 """ 2 线程通信的生产者与消费者3 python的queue模块中提供了同步的线程安全的队列类,都具有原子性,实现线程间的同步4 Queue (FIFO: fis ...

  4. Python中的进程和线程

    一.Python中两种创建进程的方式 1.os.fork只适用于Linux/Mac 2.使用multiprocessing模块可以跨平台实现多进程 使用os.fork(),像Linux平台上那样创建多 ...

  5. Python中的进程和线程(20)

    进程和线程 进程 创建多进程 进程和全局变量 传递参数和进程号 进程的状态 进程之间通信 put() get()方法 生产者和消费者 进程子类化 生产者和消费者子类化 进程池 线程 线程子类化 共享全 ...

  6. Python 中的进程、线程、协程、同步、异步、回调(一)

    在进一步之前,让我们先回顾一下各种上下文切换技术. 不过首先说明一点术语.当我们说"上下文"的时候,指的是程序在执行中的一个状态.通常我们会用调用栈来表示这个状态--栈记载了每个调 ...

  7. python中gil锁和线程锁_Python线程——GIL锁、线程锁(互斥锁)、递归锁(RLock)...

    GIL锁 ​ 计算机有4核,代表着同一时间,可以干4个任务.如果单核cpu的话,我启动10个线程,我看上去也是并发的,因为是执行了上下文的切换,让看上去是并发的.但是单核永远肯定时串行的,它肯定是串行 ...

  8. python中gil锁和线程锁_浅谈Python中的全局锁(GIL)问题

    CPU-bound(计算密集型) 和I/O bound(I/O密集型) 计算密集型任务(CPU-bound) 的特点是要进行大量的计算,占据着主要的任务,消耗CPU资源,一直处于满负荷状态.比如复杂的 ...

  9. python中基于tcp协议的通信(数据传输)

    tcp协议:流式协议(以数据流的形式通信传输).安全协议(收发信息都需收到确认信息才能完成收发,是一种双向通道的通信) tcp协议在OSI七层协议中属于传输层,它上承用户层的数据收发,下启网络层.数据 ...

最新文章

  1. 预告|开源操作系统年度技术会议
  2. Android的Intent和IntentFilter应用说明一例
  3. 分布式存储(姚文辉)
  4. labview求n阶乘的和_LABVIEW求1到N所有数的阶乘之和
  5. NSArray文件读写
  6. mysql数据库根据上传的经纬度计算距离
  7. C++(STL):17---deque之迭代器使用
  8. python实现requests访问接口,比如es接口
  9. 简述sicas计算机联锁的系统结构,《计算机联锁》教学大纲(5页)-原创力文档...
  10. python中自定义超时异常的几种方法
  11. ASP.NET MVC 5 默认模板的JS和CSS 是怎么加载的?
  12. java 挂起_Java 6 JVM挂起
  13. 八年开心网,它的是非功过都在这里了
  14. QT修改releas发布的exe图标
  15. 品味kettle--(一)用eclipse 搭建源码
  16. 万豪环保系列之水箱自洁消毒器
  17. 极限(不定式)求法总结
  18. Arcpy基础入门-3、arcpy创建地理处理工具
  19. 贵阳CBD造型怪异 或扭曲或变形
  20. C语言——PTA 稳赢

热门文章

  1. 关于EFCore线程内唯一
  2. 【ios】如何成为一名ios开发
  3. checksec未完待续~
  4. azure 使用_如何使用JavaScript在Azure上开始使用SignalR
  5. 安装meme_我见过的最好JavaScript Meme,详细说明了
  6. es6中数组的解构_ES6中的数组解构简介
  7. 智能合约怎么创建合约_可出售智能合约的协议
  8. axure 小程序 lib_【kboneui】打通 H5/微信小程序,多端UI库
  9. 蓝桥杯:试题 历届真题 修改数组【第十届】【省赛】【研究生组】Java实现
  10. Java-优先级队列(堆)