Python 通过所有函数加入线程的竞争条件
Python race condition with joining threads via all function
请查看下面的代码片段,它无法通过 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()
总是returnsNone
,所以和
一样
assert not all(None for thread in threads)
除了它有连接线程的副作用。 all()
short-circuits 第一次看到 False
值,None
是,所以实际上只调用了第一个 .join()
。 all(...)
returns False
,所以 not all(...)
returns True
,所以 assert
成功了。就像:
threads[0].join()
assert True
短期课程:任何 任何注意值 thread.join()
returns 的代码可能 flat-out 已损坏,因为 None
是它会看到的唯一值。
请查看下面的代码片段,它无法通过 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()
总是returnsNone
,所以和
assert not all(None for thread in threads)
除了它有连接线程的副作用。 all()
short-circuits 第一次看到 False
值,None
是,所以实际上只调用了第一个 .join()
。 all(...)
returns False
,所以 not all(...)
returns True
,所以 assert
成功了。就像:
threads[0].join()
assert True
短期课程:任何 任何注意值 thread.join()
returns 的代码可能 flat-out 已损坏,因为 None
是它会看到的唯一值。