实施虚拟线程而不作弊

时间:2015-06-01 19:46:29

标签: java python multithreading gevent

gevent tutorial中有一个示例如下:

import gevent

def foo():
    print('Running in foo')
    gevent.sleep(0)
    print('Explicit context switch to foo again')

def bar():
    print('Explicit context to bar')
    gevent.sleep(0)
    print('Implicit context switch back to bar')

gevent.joinall([
    gevent.spawn(foo),
    gevent.spawn(bar),
])

,输出

Running in foo
Explicit context to bar
Explicit context switch to foo again
Implicit context switch back to bar

我对它进行了测试,并亲眼看到它有效。我的一位朋友声称这完全在一个线程内运行。除了我无法想到gevent.sleep(0)的任何实现,它并没有归结为某种形式的欺骗" (即:交换前两个堆栈帧等。)

有人可以解释这是如何工作的吗?如果这是Java(或至少某种禁止这种堆栈操作的语言),这可能吗? (再次,不使用多个线程)。

1 个答案:

答案 0 :(得分:0)

它确实只在1个线程上运行。 gevent使用greenlets,它们是协程,而不是线程。每个给定时间只有1个堆栈(除非您使用多线程,然后在每个线程中使用greenlet)。

在上面的示例中,无论何时调用sleep或joinall,当前的协程(greenlet)实际上都会产生到集线器。将中心视为中央调度员,负责决定下一步将运行哪个协程。

为了说服自己,删除gevent.sleep(0)调用,你会发现它的行为不同。

请注意,与线程不同,执行是确定性的,因此如果您运行程序两次,它将以完全相同的顺序执行。