python多线程同步---事件 Event

事件 Event是另一种python多线程同步技术, 本文将使用python语言对这种技术进行讲解, 想象这样一个场景,你启动了多个线程,这些线程都要去访问一个资源,但是,这里有一个小小的问题,即将被访问的资源还没有准备好接受访问,那么此时,多个线程去访问,必然得到不响应,你还得处理这种得不到响应的情况

1. Event

借助Event,可以灵活的协调线程间的操作,它提供了下面几个方法

1.1 set()

将事件内部标识设置为True,Event对象最初创建时,内部标识默认是False

1.2 wait()

当在线程中调用wait时,如果事件内部标识为False,则会阻塞,直到set方法被调用,将内部标识设置为True

1.3 clear()

将内部标识重新设置为False

1.4 is_set()

如果内部标识是True,则返回True,反之,返回False

2. 协调线程同步

想象这样一个场景,你启动了多个线程,这些线程都要去访问一个资源,但是,这里有一个小小的问题,即将被访问的资源还没有准备好接受访问,那么此时,多个线程去访问,必然得到不响应,你还得处理这种得不到响应的情况。

这样的场景下,能否先在主线程里去做试探,确定资源可以访问以后,再让已经启动了的多线程去访问呢?让我们考虑一下如何用Event来处理这样的问题

  1. 创建一个Event对象,现在,事件内部标识是False
  2. 启动多线程,线程里调用wait方法,这时,会阻塞
  3. 主线程去试探,确定资源可访问以后,调用set方法
  4. 已经调用wait的线程接手到事件信息,访问资源

以下为示例代码

import threading
from threading import Event


def worker(event_obj, i):
    print('{i}号线程等待事件信号'.format(i=i))
    event_obj.wait()
    print('{i}号线程收到事件信号'.format(i=i))


event = Event()

for i in range(5):
    t = threading.Thread(target=worker, args=(event, i))
    t.start()

print('确认资源可用')
event.set()

3. 一个更复杂的例子

一个线程依次打印1 3 5 ,一个线程依次打印 2 4 6,使用事件做消息同步,使得两个线程启动后,打印出1 2 3 4 5 6, 别看要求很简单,但实现起来却是有难度的,每个线程输出不同的数列,但整体上看却要求有序。

针对这样的线程同步要求,可以创建两个Event对象,两个线程互相触发另一个线程的Event对象

import threading
from threading import Event


def print_a(e1, e2):
    for item in [1, 3, 5]:
        e1.wait()
        print(item)
        e1.clear()
        e2.set()


def print_b(e1, e2):
    for item in [2, 4, 6]:
        e1.wait()
        print(item)
        e1.clear()
        e2.set()

e1, e2 = Event(), Event()
t1 = threading.Thread(target=print_a, args=(e1, e2))
t2 = threading.Thread(target=print_b, args=(e2, e1))
t1.start()
t2.start()
e1.set()

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案