Go 的多线程和 pthread 或 Java Threads 有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1739614/
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
What is the difference between Go's multithreading and pthread or Java Threads?
提问by Frank
What is the difference between Go's multithreading approach and other approaches, such as pthread, boost::thread or Java Threads?
Go 的多线程方法与其他方法(例如 pthread、boost::thread 或 Java Threads)有什么区别?
采纳答案by Randy Sugianto 'Yuku'
Quoted from Day 3 Tutorial<- read this for more information.
引自第 3 天教程<- 阅读本文了解更多信息。
Goroutines are multiplexed as needed onto system threads. When a goroutine executes a blocking system call, no other goroutine is blocked.
We will do the same for CPU-bound goroutines at some point, but for now, if you want user-level parallelism you must set $GOMAXPROCS. or call runtime.GOMAXPROCS(n).
Goroutines 根据需要多路复用到系统线程上。当一个 goroutine 执行阻塞系统调用时,没有其他 goroutine 被阻塞。
我们会在某个时候对 CPU 绑定的 goroutine 做同样的事情,但是现在,如果你想要用户级并行,你必须设置 $GOMAXPROCS。或调用 runtime.GOMAXPROCS(n)。
A goroutine does not necessarily correspond to an OS thread. It can have smaller initial stack size and the stack will grow as needed.
goroutine 不一定对应于 OS 线程。它可以具有较小的初始堆栈大小,并且堆栈将根据需要增长。
Multiple gorouitines may be multiplexed into a single thread when needed.
需要时可以将多个 gorouitines 多路复用到单个线程中。
More importantly, the concept is as outlined above, that a goroutine is a sequential program that may block itself but does not block other goroutines.
更重要的是,概念如上所述,goroutine 是一个顺序程序,它可以阻塞自己但不会阻塞其他 goroutine。
Goroutines is implemented as pthreads in gccgo, so it can be identical to OS thread, too. It's separating the concept of OS thread and our thinking of multithreading when programming.
Goroutines 在 gccgo 中作为 pthreads 实现,因此它也可以与 OS 线程相同。它分离了操作系统线程的概念和我们在编程时对多线程的思考。
回答by floodyberry
In the reference compilers (5g/6g/8g), the master scheduler (src/pkg/runtime/proc.c) creates N OS threads, where N is controlled by runtime.GOMAXPROCS(n) (default 1). Each scheduler thread pulls a new goroutine off the master list and starts running it. The goroutine(s) will continue to run until a syscall is made (e.g. printf) or an operation on a channel is made, at which point the scheduler will grab the next goroutine and run it from the point at which it left off (see gosched() calls in src/pkg/runtime/chan.c).
在参考编译器 (5g/6g/8g) 中,主调度程序 ( src/pkg/runtime/proc.c) 创建 N 个操作系统线程,其中 N 由 runtime.GOMAXPROCS(n) 控制(默认为 1)。每个调度程序线程从主列表中拉出一个新的 goroutine 并开始运行它。goroutine 将继续运行,直到进行系统调用(例如 printf)或对通道进行操作,此时调度程序将获取下一个 goroutine 并从它停止的点运行它(参见gosched() 在src/pkg/runtime/chan.c 中调用)。
The scheduling, for all intents and purposes, is implemented with coroutines. The same functionality could be written in straight C using setjmp() and longjmp(), Go (and other languages that implement lightweight/green threads) are just automating the process for you.
出于所有意图和目的,调度是通过coroutines实现的。可以使用 setjmp() 和 longjmp() 用直接的 C 语言编写相同的功能,Go(以及其他实现轻量级/绿色线程的语言)只是为您自动执行该过程。
The upside to lightweight threads is since it's all userspace, creating a "thread" is very cheap (allocating a small default stack) and can be very efficient due to the inherent structure of how the threads talk to eachother. The downside is that they are not true threads which means a single lightweight thread can block the entire program, even when it appears all the threads should be running concurrently.
轻量级线程的好处是因为它都是用户空间,创建一个“线程”非常便宜(分配一个小的默认堆栈)并且由于线程如何相互通信的固有结构而非常有效。缺点是它们不是真正的线程,这意味着单个轻量级线程可以阻塞整个程序,即使看起来所有线程都应该并发运行。
回答by jldupont
IMO, what makes the multi-threading in Go appealing is the communication facilities: unlike pthread where one must build the communications infrastructure (mutex, queues etc.), in Go it is available by default in a convenient form.
IMO,让 Go 中的多线程吸引人的是通信设施:与必须构建通信基础设施(互斥、队列等)的 pthread 不同,在 Go 中,它默认以一种方便的形式提供。
In short, there is "low-friction" to using threads because of the good communicationfacilities (akin to Erlang if I can say so).
简而言之,由于良好的通信设施(如果我可以这么说,类似于 Erlang),使用线程具有“低摩擦”。
回答by Programster
As previous answers have stated, go routines do not necessarily correspond to system threads however I found the following useful if you must have the performance increase of multi-threading right now:
正如之前的答案所述,go 例程不一定对应于系统线程,但是如果您现在必须提高多线程的性能,我发现以下内容很有用:
The current implementation of the Go runtime will not parallelizethis code by default. It dedicates only a single core to user-level processing. An arbitrary number of goroutines can be blocked in system calls, but by default only one can be executing user-level code at any time. It should be smarter and one day it will be smarter, but until it is if you want CPU parallelism you must tell the run-time how many goroutines you want executing code simultaneously. There are two related ways to do this. Either run your job with environment variable GOMAXPROCS set to the number of cores to use or import the runtime package and call runtime.GOMAXPROCS(NCPU). A helpful value might be runtime.NumCPU(), which reports the number of logical CPUs on the local machine. Again, this requirement is expected to be retired as the scheduling and run-time improve.
默认情况下,Go 运行时的当前实现不会并行化此代码。它仅将一个内核专用于用户级处理。可以在系统调用中阻塞任意数量的 goroutine,但默认情况下,任何时候只有一个可以执行用户级代码。它应该更智能,总有一天它会更智能,但是直到你想要 CPU 并行性,你必须告诉运行时你想要同时执行多少个 goroutines. 有两种相关的方法可以做到这一点。使用设置为要使用的内核数的环境变量 GOMAXPROCS 运行您的作业,或者导入运行时包并调用 runtime.GOMAXPROCS(NCPU)。一个有用的值可能是 runtime.NumCPU(),它报告本地机器上的逻辑 CPU 的数量。同样,随着调度和运行时间的改进,预计此要求将被取消。
An example program that maxes out my i5 processor is this (uses all 4 cores at 100% in htop):
一个使我的 i5 处理器最大化的示例程序是这样的(在 htop 中以 100% 使用所有 4 个内核):
package main
import (
"fmt"
"time"
"runtime"
)
func main() {
runtime.GOMAXPROCS(4) // Set the maximum number of threads/processes
d := make(chan string)
go boring("boring!", d, 1)
go boring("boring!", d, 2)
go boring("boring!", d, 3)
go boring("boring!", d, 4)
for i := 0; i < 10; i++ {
time.Sleep(time.Second);
}
fmt.Println("You're boring; I'm leaving.")
}
func boring(msg string, c chan string, id int) {
for i := 0; ; i++ {
}
}
Now that doesn't actually 'do' anything, but see how short/easy/simple that is compared to writing multithreaded applications in other languages such as Java.
现在这实际上并没有“做”任何事情,但是看看与使用其他语言(例如 Java)编写多线程应用程序相比,它是多么短/容易/简单。

