multithreading Go goroutine 是协程吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18058164/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is a Go goroutine a coroutine?
提问by S?awosz
In the Google I/O 2012 presentation Go Concurrency Patterns, Rob Pike mentions that several goroutinescan live in one thread. Does this imply that they are implemented as coroutines? If not, how they are implemented? Links to source code would be welcome.
在 Google I/O 2012 演讲Go Concurrency Patterns 中,Rob Pike 提到多个goroutine可以存在于一个线程中。这是否意味着它们是作为协程实现的?如果没有,它们是如何实施的?欢迎提供源代码链接。
采纳答案by K Z
Not quite. The Go FAQ section Why goroutines instead of threads?explains:
不完全的。Go FAQ 部分为什么使用 goroutine 而不是线程?解释:
Goroutines are part of making concurrency easy to use. The idea, which has been around for a while, is to multiplex independently executing functions—coroutines—onto a set of threads. When a coroutine blocks, such as by calling a blocking system call, the run-time automatically moves other coroutines on the same operating system thread to a different, runnable thread so they won't be blocked. The programmer sees none of this, which is the point. The result, which we call goroutines, can be very cheap: they have little overhead beyond the memory for the stack, which is just a few kilobytes.
To make the stacks small, Go's run-time uses resizable, bounded stacks. A newly minted goroutine is given a few kilobytes, which is almost always enough. When it isn't, the run-time grows (and shrinks) the memory for storing the stack automatically, allowing many goroutines to live in a modest amount of memory. The CPU overhead averages about three cheap instructions per function call. It is practical to create hundreds of thousands of goroutines in the same address space. If goroutines were just threads, system resources would run out at a much smaller number.
Goroutines 是使并发易于使用的一部分。这个想法已经存在一段时间了,它是将独立执行的函数——协程——复用到一组线程上。当协程阻塞时,例如通过调用阻塞系统调用,运行时会自动将同一操作系统线程上的其他协程移动到不同的可运行线程,这样它们就不会被阻塞。程序员看不到这些,这才是重点。结果,我们称之为 goroutines,可以非常便宜:除了堆栈的内存之外,它们几乎没有开销,只有几千字节。
为了使堆栈变小,Go 的运行时使用可调整大小的有界堆栈。一个新创建的 goroutine 被赋予几千字节,这几乎总是足够的。如果不是,运行时会自动增加(和收缩)用于存储堆栈的内存,从而允许许多 goroutine 存在于适度的内存中。每个函数调用的 CPU 开销平均约为 3 条廉价指令。在同一个地址空间中创建数十万个 goroutine 是可行的。如果 goroutine 只是线程,那么系统资源会以更少的数量耗尽。
回答by kostix
IMO, a coroutine implies supporting of explicitmeans for transferring control to another coroutine. That is, the programmer programs a coroutine in a way when they decide when a coroutine should suspend execution and pass its control to another coroutine (either by calling it or by returning/exiting (usually called yielding)).
IMO,协程意味着支持将控制转移到另一个协程的显式方法。也就是说,程序员在决定协程何时应该暂停执行并将其控制权传递给另一个协程(通过调用它或通过返回/退出(通常称为让步))时,以某种方式对协程进行编程。
Go's "goroutines" are another thing: they implicitlysurrender control at certain indeterminatepoints1which happen when the goroutine is about to sleep on some (external) resource like I/O completion, channel send etc. This approach combined with sharing state via channels enables the programmer to write the program logic as a set of sequentiallight-weight processes which removes the spaghetti code problem common to both coroutine- and event-based approaches.
Go 的“goroutines”是另一回事:它们在某些不确定点1隐式交出控制权,这发生在 goroutine 即将在某些(外部)资源(如 I/O 完成、通道发送等)上休眠时。这种方法与通过通道共享状态相结合使程序员能够将程序逻辑编写为一组连续的轻量级进程,从而消除了基于协程和基于事件的方法常见的意大利面条式代码问题。
Regarding the implementation, I think they're quite similar to the (unfortunately not too well-known) "State Threads" library, just quite lower-level (as Go doesn't rely on libc
or things like this and talks directly to the OS kernel) — you could read the introductory paper for the ST library where the concept is quite well explained.
关于实现,我认为它们与(不幸的是不太知名的)“状态线程”库非常相似,只是级别较低(因为 Go 不依赖libc
或类似的东西,直接与操作系统对话内核)——您可以阅读 ST 库的介绍性论文,其中对概念进行了很好的解释。
1In fact, these points are less determinate than those of coroutines but more determinate than with true OS threads under preemptive multitasking, where each thread might be suspended by the kernel at any given point in time and in the flow of the thread's control.
1事实上,这些点不如协程确定,但比抢占式多任务下的真正操作系统线程更确定,其中每个线程可能在任何给定的时间点和线程控制流中被内核挂起。
回答by Volker
Whether a goroutine is a proper coroutine or just something similar is often discussed on https://groups.google.com/forum/?fromgroups=#!forum/golang-nuts. Some people can argue about such subtleties, but for most of it: goroutine is a coroutine.
goroutine 是适当的协程还是类似的东西经常在https://groups.google.com/forum/?fromgroups=#!forum/golang-nuts 上讨论。有些人可能会争论这些微妙之处,但对于大多数人来说:goroutine 是一个协程。
Have a look at https://docs.google.com/document/d/1TTj4T2JO42uD5ID9e89oa0sLKhJYD0Y_kqxDv3I3XMw/editto understand how the scheduler works.
查看https://docs.google.com/document/d/1TTj4T2JO42uD5ID9e89oa0sLKhJYD0Y_kqxDv3I3XMw/edit以了解调度程序的工作原理。
回答by zzzz
Goroutine is a separate "thread" of execution. It is IMO not really comparable to a coroutine. In the first approximation, goroutines can be implemented by realOS threads. AFAIK, that was the case of early versions of gccgo. Another difference is that goroutines can get preempted.
Goroutine 是一个单独的执行“线程”。IMO 不能与协程相提并论。在第一个近似中,goroutine 可以由真实的OS 线程实现。AFAIK,这是gccgo早期版本的情况。另一个区别是 goroutine 可以被抢占。
Current Go compilers implement goroutines as very lightweight, user space "threads". One distinct feature wrt to eg. green threadsis that goroutines can get switched to different OS threads.
当前的 Go 编译器将 goroutine 实现为非常轻量级的用户空间“线程”。一个独特的功能,例如。绿色线程是 goroutine 可以切换到不同的操作系统线程。
I think you can find some related bits of interest here: proc.c
我想你可以在这里找到一些相关的兴趣点:proc.c