通过以下代码,我想展示如何与线程同步。
您可以在下面找到相应的代码。它在等待第一张图像时卡住了。
为什么notify_all没有释放image_created.wait?
# Output
create new image
waiting for new image
start waiter
notify_all
wait for someone to take it
waiting for image_created
import asyncio
import random
import threading
import time
class ImageUpdater:
def __init__(self):
self.image = None
self.image_used = threading.Event()
self.image_created = threading.Condition()
def update_image(self):
while True:
self.image_used.clear()
with self.image_created:
print("create new image")
time.sleep(0.6)
self.image = str(random.random())
print("notify_all")
self.image_created.notify_all()
print("wait for someone to take it")
self.image_used.wait()
print("someone took it")
async def image_generator(self):
def waiter():
print("start waiter")
time.sleep(0.1)
with self.image_created:
print("waiting for image_created")
self.image_created.wait()
print("waiter finished")
self.image_used.set()
while True:
print("waiting for new image")
await asyncio.to_thread(waiter)
yield self.image
async def main():
updater = ImageUpdater()
update_thread = threading.Thread(target=updater.update_image)
update_thread.start()
async for image in updater.image_generator():
print(f"Received new image: {image}")
if __name__ == "__main__":
loop = asyncio.run(main())
代码中的问题在于 image_created.wait() 没有在主线程中正确唤醒。这背后的原因是图像创建和通知是在 self.image_created 的块内完成的,并且该块在调用 notification_all() 之前关闭。因此,当异步生成器尝试等待 image_created.wait() 时,没有发生任何通知。
def update_image(self):
while True:
self.image_used.clear()
with self.image_created:
print("create new image")
time.sleep(0.6)
self.image = str(random.random())
print("notify_all")
self.image_created.notify_all()
print("wait for someone to take it")
self.image_used.wait()
print("someone took it")