简体   繁体   English

实施虚拟线程而不作弊

[英]Implementing virtual threads without cheating

In the gevent tutorial there's an example that looks like this: gevent教程中有一个如下所示的示例:

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),
])

and the output is 而输出是

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

I've tested it and seen for myself that it works. 我测试了它,并亲眼看到它的工作原理。 A friend of mine claims this is run entirely within a single thread. 我的一位朋友声称这完全在一个线程内运行。 Except that I can't think of any implementation of gevent.sleep(0) which doesn't boil down to some form of "cheating" (ie: Swap the top two stack frames etc.) 除了我不能想到gevent.sleep(0)的任何实现,它不能归结为某种形式的“作弊”(即:交换前两个堆栈帧等)

Can someone explain how this works? 谁能解释一下这是如何工作的? If this were Java (or at least some language where that kind of stack manipulation is forbidden), would this be possible? 如果这是Java(或至少某种禁止这种堆栈操作的语言),这可能吗? (again, without using multiple threads). (再次,不使用多个线程)。

It indeed runs on only 1 thread. 它确实只在1个线程上运行。 gevent uses greenlets, which are coroutines, not threads. gevent使用greenlets,它们是协程,而不是线程。 There is only 1 stack at each given time (unless you use multithreading, and then use greenlets in each threads). 每个给定时间只有1个堆栈(除非您使用多线程,然后在每个线程中使用greenlet)。

In your example above, whenever you call sleep or joinall, the current coroutine (greenlet) actually yields to the hub. 在上面的示例中,无论何时调用sleep或joinall,当前的协程(greenlet)实际上都会向hub发送。 Think about the hub as a central dispatcher, responsible to decide which coroutine will run next. 将集线器视为中央调度员,负责决定下一步将运行哪个协同程序。

To convince yourself of that, remove the gevent.sleep(0) call, and you'll see that it behaves differently. 为了说服自己,删除gevent.sleep(0)调用,你会发现它的行为不同。

Note that unlike threads, the execution is deterministic, so if you run the program twice, it will execute in the exact same order. 请注意,与线程不同,执行是确定性的,因此如果您运行程序两次,它将以完全相同的顺序执行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM