通过所有函数连接线程的Python竞争条件



请参阅下面的代码片段,它无法通过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是它唯一看到的值。

最新更新