请参阅下面的代码片段,它无法通过Python 3.10在本地运行的第一次。
当我尝试join
内置all
函数内的所有线程时,总是有一个线程仍然活着。
这里的问题是什么,为什么会发生竞态条件?
import time
from threading import Thread
def expose_race_condition(run_index: int) -> None:
threads: list[Thread] = [
Thread(target=time.sleep, args=(1,)) for _ in range(10)
]
for thread in threads:
thread.start()
# RACE CONDITION IS HERE
assert not all(thread.join() for thread in threads)
for thread_index, thread in enumerate(threads):
# Uncommenting the below line defeats the race condition
# assert not thread.join()
assert (
not thread.is_alive()
), f"Worker {thread_index} in run {run_index} was still alive."
print(f"Completed run {run_index}")
if __name__ == "__main__":
for i in range(10_000):
expose_race_condition(i)
对不起,我不明白你想干什么。这一行,例如:
assert not all(thread.join() for thread in threads)
就是没有意义。.join()
总是返回None
,所以它与
assert not all(None for thread in threads)
除了它有连接线程的副作用。all()
在第一次看到False
值时短路,而None
是,因此实际上只调用第一个.join()
。all(...)
返回False
,因此not all(...)
返回True
,因此assert
成功。这就像:
threads[0].join()
assert True
简而言之:任何代码关注thread.join()
返回的值都可能是完全错误的,因为None
是它唯一看到的值。