为什么是条件.全部通知只叫醒一个服务员?

2024-06-11 20:06:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图创建一个python异步版本的java的CountDownLatch

class CountDownLatch:
    def __init__(self, count=1):
        if count == 0:
            raise ValueError('count should be more than zero')
        self.count = count
        self.countdown_over = aio.Condition()

    async def countdown(self):
        with await self.countdown_over:
            print('decrementing counter')
            self.count -= 1
            print('count {}'.format(self.count))
            if self.count == 0:
                print('count is zero no more waiting')
                await aio.sleep(1)
                self.countdown_over.notify_all()

    async def wait(self):
        with await self.countdown_over:
            await self.countdown_over.wait()

现在我在试。你知道吗

In [2]: async def g(latch):
   ...:     await latch.wait()
   ...:     print('g')
   ...:

In [3]: async def f(latch):
   ...:     print('counting down')
   ...:     await latch.countdown()
   ...:     await g(latch)
   ...:

In [4]: def run():
   ...:     latch = CountDownLatch(2)
   ...:     loop = aio.get_event_loop()
   ...:     loop.run_until_complete(aio.wait((f(latch), f(latch))))
   ...:

In [5]: import asyncio as aio

In [6]: from new.tests.test_turnovers import CountDownLatch

这是输出

counting down
decrementing counter
count 1
counting down
decrementing counter
count 0
count is zero no more waiting
g

我不明白我做错了什么。计数器的创建和递减都很好。一个协同程序甚至被通知并继续它的任务,但是第二个由于某种原因没有。你知道吗


Tags: inselfasyncdefmorecountawaitover
1条回答
网友
1楼 · 发布于 2024-06-11 20:06:58

f1f称为第一个,让f2f称为第二个。需要注意的是,即使您使用了async关键字f,函数也是同步的,直到它到达latch.wait()。所以我们可以很容易地调试正在发生的事情:

  1. f1开火。你知道吗
  2. count减少1
  3. f1进入await self.countdown_over.wait()上下文切换发生
  4. f2开火
  5. count减少1f2进入if状态
  6. self.countdown_over.notify_all()开火。所有的服务员都会得到通知(注意,此时只有f1)。你知道吗
  7. f2进入await self.countdown_over.wait()上下文切换发生
  8. f1醒来并离开.wait()呼叫

注意,步骤7发生在步骤6之后。因此f2从不被通知。你知道吗

通常,如果有多个线程(绿色或非绿色)通知并等待(按此顺序同步),那么至少有一个线程将始终无法继续。你知道吗

相关问题 更多 >