【问题标题】:Is it a bug of the 'wait' method of gevent.event.Event?它是 gevent.event.Event 的“等待”方法的错误吗?
【发布时间】:2013-12-06 07:22:04
【问题描述】:

我写了一个脚本来玩gevent.event.Event,但是我发现wait方法好像没有生效。我使用的gevent版本是1.0。

我的脚本如下,你也可以得到here

#!/urs/bin/env python2.7
#coding: utf-8

"""Test the usage of 'gevent.event.Event' class.
"""

import random

import gevent
from gevent.event import Event


class TestEvent(object):
    def __init__(self):
        self.event = Event()

    def run(self):
        producers = [gevent.spawn(self._producer, i) for i in xrange(3)]
        consumers = [gevent.spawn(self._consumer, i) for i in xrange(3)]
        tasks     = []
        tasks.extend(producers)
        tasks.extend(consumers)
        gevent.joinall(tasks)

    def _producer(self, pid):
        print("I'm producer %d and now I don't want consume to do something" % (pid,))
        self.event.clear()
        sleeptime = random.randint(0, 5) * 0.01
        print("Sleeping time is %f" % (sleeptime, ))
        gevent.sleep(sleeptime)
        print("I'm producer %d and now consumer could do something." % (pid,))
        self.event.set()

    def _consumer(self, pid):
        print("I'm consumer %d and now I'm waiting for producer" % (pid,))
        flag = self.event.wait()
        print("I'm consumer %d. Flag is %r and now I can do something" % (pid, flag))
        self.event.clear()


if __name__ == '__main__':
    test = TestEvent()
    test.run()

脚本的输出为:

【问题讨论】:

  • 您期待什么?你得到的输出有什么问题?
  • @DavidSchwartz,如果 Event()._flagFalse,则 wait() 方法应阻止当前的greenlet,但它没有显示。
  • 你怎么知道它没有?不清楚为什么你会觉得这令人惊讶。您是否有任何证据表明消费者在标志为真时没有被阻止,在它调用等待和等待返回之间?
  • 我在 _consumer 中获取标志值,然后打印出来。输出显示当标志为 False 时,_consumer 仍然运行而不是阻塞。
  • 你知道两件事:1)标志从真到假。 2)线程醒来。由此,您得出结论,线程在标志为假时唤醒。这个结论没有证据支持。

标签: python-2.7 gevent


【解决方案1】:

您的制作人执行以下操作:

P-A:清除事件
P-B:设置事件

您的消费者执行以下操作:

C-A:等待事件设置
C-B:设置事件时唤醒
C-C:获取事件值返回
C-D:清除事件

您在生产者和消费者之间或消费者和彼此之间不强制执行排序,因此可能会发生这种情况:

P-A(事件明确)
C1-A
C2-A
C3-A(三个消费者都在等待)
P-B(事件已设置)
C1-B
C2-B
C3-B(所有消费者都已醒来,因为设置了事件)
C1-C(消费者 1 将事件视为已设置)
C1-D(消费者1已清除事件)
C2-C(消费者 2 认为事件是明确的)
C3-C(消费者 3 认为事件是明确的)
C2-D
C3-D
...

【讨论】:

  • 是不是说如果有很多消费者等待flag为True,而一个producer设置flag为True,那么所有的consumer都醒了,不再阻塞等待由 hub greenlet 调度,即使其他操作将标志设置为 False?
  • 是的。设置事件后,所有等待的绿灯都将被畅通。当他们醒来时,旗帜就是原来的样子。
  • 我明白了。非常感谢你! :D
猜你喜欢
  • 2013-01-17
  • 1970-01-01
  • 1970-01-01
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 2020-06-20
相关资源
最近更新 更多