以下是使用條件對象的示例。
from threading import Thread, Condition, Lock
from time import sleep
from random import random
_lock = Lock()
def run(idx, condition):
sleep(random() * 3)
print('thread_%d is waiting for notifying main thread.' % idx)
_lock.acquire()
with condition:
print('thread_%d notifies main thread.' % idx)
condition.notify()
def is_working(thread_list):
for t in thread_list:
if t.is_alive():
return True
return False
def main():
condition = Condition(Lock())
thread_list = [Thread(target=run, kwargs={'idx': i, 'condition': condition}) for i in range(10)]
with condition:
with _lock:
for t in thread_list:
t.start()
while is_working(thread_list):
_lock.release()
if condition.wait(timeout=1):
print('do something')
sleep(1) # <-- Main thread is doing something.
else:
print('timeout')
for t in thread_list:
t.join()
if __name__ == '__main__':
main()
我不認爲你有評論中描述的競爭條件。條件對象包含一個Lock。當主線程正在工作(例子中爲sleep(1))時,它保存該鎖,並且沒有線程可以通知它,直到它完成工作並釋放鎖。
我剛剛意識到在前面的例子中存在競爭條件。我添加了一個全局_lock來確保條件從不通知主線程,直到主線程開始等待。我不喜歡它是如何工作的,但我還沒有想出更好的解決方案...
也許條件對象?主線程等待條件對象。 t1和t2在返回之前調用condition_obj.notify()。返回的線程首先喚醒主線程。這裏是條件對象的文檔:[鏈接](https://docs.python.org/3/library/threading.html#condition-objects) –
我在這裏看到競爭條件:想象t1完成並稱爲「通知」 ,主線程醒來,做一些東西,並想再次入睡(等待t2,t3,t4等)。可能發生的情況是,在主線程中「做某些事情」時,有些甚至全部t2,... t4線程將完成其工作並調用「通知」。然後主線程會叫「等待」並永遠睡眠,因爲沒有人再喚醒它。 – ilya
沒有比賽條件。條件對象包含一個RLock。我稍後會發佈一個例子。 –