0

首先,理想情况下,以下代码应该同步运行 3 个 greenlets,但它会异步运行所有 3 个 greenlets。然而奇怪的事情是不管你有多少个greenlet,它都会为第二个greenlet启动一个额外的同步过程。我不是问这个问题的解决方法,只是我想了解这背后的原因。

import gevent
import time

def func(i):
    t = time.time()
    print('func %s started at %s' % (i, t))
    secs = 5
    statement = "after %s secs" % secs
    gevent.sleep(secs)
    print('func %s stopped in %s secs' % (i, (time.time() - t)))

apps = [gevent.Greenlet.spawn(func, i) for i in range(3)]

[app.run() for app in apps]

这是示例标准输出:

func 0 started at 1491859273.2895772
func 1 started at 1491859273.2898045
func 2 started at 1491859273.2899446
func 0 stopped in 5.0095603466033936 secs
func 1 started at 1491859278.2993205
func 1 stopped in 5.0163233280181885 secs
func 2 stopped in 5.019707918167114 secs
func 1 stopped in 5.009198188781738 secs

怎么会func 1 started发生两次?

4

1 回答 1

0

当您调用spawn(). 直接调用run()不是公开记录的 API 的一部分,其效果未定义。那么,任何关于为什么观察到当前行为的描述都需要超越记录在案的 API 进入实现细节。

用于gevent.joinall()等待您已经安排好的工作完成。

apps = [gevent.Greenlet.spawn(func, i) for i in range(3)]
gevent.joinall(apps)

正确产生:

func 0 started at 1491921603.6
func 1 started at 1491921603.6
func 2 started at 1491921603.6
func 0 stopped in 5.00121307373 secs
func 1 stopped in 5.00118613243 secs
func 2 stopped in 5.0011780262 secs

现在,让我们深入研究一下这种未定义的行为,并了解它很容易因版本或系统而异。

运行两次的特别是 Greenlet 1 的原因是当主控制线程第一次合作让步时发生的意外。您可以通过在第一次调用之前显式让步来更改此行为:run()

print "=== About to spawn greenlets..."
apps = [gevent.Greenlet.spawn(func, i) for i in range(3)]
print "=== All greenlets spawned; yielding..."
gevent.sleep(0)
print "=== Calling a duplicate run() invocation on each"
result = [app.run() for app in apps]

有了这个改变,greenlet 0首先开始——你会注意到它在被调用之前开始: run()

=== About to spawn greenlets...
=== All greenlets spawned; yielding...
func 0 started at 1491921486.57
func 1 started at 1491921486.57
func 2 started at 1491921486.57
=== Calling a duplicate run() invocation on each
func 0 started at 1491921486.57
func 0 stopped in 5.00335502625 secs
func 1 stopped in 5.00336790085 secs
func 2 stopped in 5.0033519268 secs
func 0 stopped in 5.0033428669 secs
于 2017-04-11T14:30:05.510 回答