为什么threading.Condition.notfiy_all没有触发等待线程继续?

问题描述 投票:0回答:1

通过以下代码,我想展示如何与线程同步。

  • 我想要一个单独的线程来更新图像。
  • 从这些图像中,我想要一个异步生成器。
  • 图像仅应在异步生成器使用时更新。
  • 异步生成器应该等待创建新图像。

您可以在下面找到相应的代码。它在等待第一张图像时卡住了。

为什么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())

python python-asyncio python-multithreading
1个回答
0
投票

代码中的问题在于 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")
© www.soinside.com 2019 - 2024. All rights reserved.