python threading:Event.set()会真正通知每个等待的线程

Cri*_*iss 17 python events multithreading wait

如果我有一个threading.Event和以下两行代码......

event.set()
event.clear()
Run Code Online (Sandbox Code Playgroud)

...我有一些线程在等待那个事件.

我的问题与调用set()方法时会发生什么有关:

  • 我可以绝对确定所有等待的线程都会收到通知吗?(即Event.set()"通知"线程)
  • 或者可能会发生这两行在彼此之后如此快速地执行,某些线程可能仍在等待?(即Event.wait()轮询事件的状态,该状态可能已经被"清除"了)

谢谢你的回答!

Vin*_*jip 13

很容易验证事情按预期工作:

import threading

e = threading.Event()
threads = []

def runner():
    tname = threading.current_thread().name
    print 'Thread waiting for event: %s' % tname
    e.wait()
    print 'Thread got event: %s' % tname

for t in range(100):
    t = threading.Thread(target=runner)
    threads.append(t)
    t.start()

raw_input('Press enter to set and clear the event:')
e.set()
e.clear()
for t in threads:
    t.join()
print 'All done.'
Run Code Online (Sandbox Code Playgroud)

如果你运行上面的脚本并且终止,那么一切都应该很好:-)请注意,有一百个线程正在等待设置事件; 它立即设置并清除; 所有线程都应该看到这个并且应该终止(虽然没有任何明确的顺序,并且"All done"可以在"按Enter"提示后的任何地方打印,而不仅仅是在最后.


Céd*_*ien 11

在Python的内部,使用Condition()对象实现事件.

调用event.set()方法时,调用notify_all()条件(在获取锁定以确保不被中断之后),然后所有线程都接收通知(只有在通知所有线程时才释放锁定),因此您可以确保所有线程都能得到有效通知.

现在,在通知之后清除事件不是问题....直到您不想在等待线程中检查事件值event.is_set(),但是如果您等待超时则只需要这种检查.

例子 :

有效的伪代码:

#in main thread
event = Event()
thread1(event)
thread2(event)
...
event.set()
event.clear()

#in thread code
...
event.wait()
#do the stuff
Run Code Online (Sandbox Code Playgroud)

伪代码可能不起作用:

#in main thread
event = Event()
thread1(event)
thread2(event)
...
event.set()
event.clear()

#in thread code
...
while not event.is_set():
   event.wait(timeout_value)
#do the stuff
Run Code Online (Sandbox Code Playgroud)

编辑:在python> = 2.7中,您仍然可以等待超时的事件,并确保事件的状态:

event_state = event.wait(timeout)
while not event_state:
    event_state = event.wait(timeout)
Run Code Online (Sandbox Code Playgroud)