Go的多线程方法和其他方法有什么区别,比如pthread,boost :: thread或Java Threads?
答案 0 :(得分:23)
引自Day 3 Tutorial< - 请阅读此内容以获取更多信息。
Goroutines根据需要进行多路复用 到系统线程。当一个goroutine 执行阻塞系统调用,没有 其他goroutine被阻止了。
我们将对CPU绑定做同样的事情 goroutines在某些时候,但现在, 如果你想要用户级并行性 必须设置$ GOMAXPROCS。或者打电话 runtime.GOMAXPROCS(n)的
goroutine不一定对应于OS线程。它可以具有较小的初始堆栈大小,并且堆栈将根据需要增长。
多个gououitine可在需要时多路复用到单个线程中。
更重要的是,这个概念如上所述,goroutine是一个顺序程序,可以阻止自己,但不会阻止其他goroutines。
Goroutines在gccgo中实现为pthread,因此它也可以与OS线程相同。 它将OS线程的概念与编程时的多线程思想分开。
答案 1 :(得分:14)
在参考编译器(5g / 6g / 8g)中,主调度程序(src/pkg/runtime/proc.c)创建N OS线程,其中N由runtime.GOMAXPROCS(n)(默认值1)控制。每个调度程序线程从主列表中提取一个新的goroutine并开始运行它。 goroutine将继续运行,直到进行系统调用(例如printf)或对通道进行操作,此时调度程序将抓取下一个goroutine并从它停止的位置运行它(参见gosched()调用src/pkg/runtime/chan.c)。
所有意图和目的的调度都是使用coroutines实现的。可以使用setjmp()和longjmp()直接用C编写相同的功能,Go(以及实现轻量级/绿色线程的其他语言)只是为您自动化过程。
轻量级线程的好处是因为它是所有用户空间,创建“线程”非常便宜(分配一个小的默认堆栈)并且由于线程如何相互通信的固有结构而非常有效。缺点是它们不是真正的线程,这意味着单个轻量级线程可以阻止整个程序,即使它看起来所有线程都应该同时运行。
答案 2 :(得分:13)
IMO,使Go中的多线程吸引人的是通信设施:与pthread不同,其中必须构建通信基础设施(互斥,队列等),在Go中它默认以方便的形式提供。
简而言之,由于良好的沟通设施,使用线程存在“低摩擦”(如果可以的话,就像Erlang一样)。
答案 3 :(得分:5)
正如之前的答案所述,go例程并不一定与系统线程相对应,但是如果你现在必须提高多线程的性能,我发现以下内容很有用:
默认情况下,Go运行时的当前实现不会并行化此代码。它仅将单个核心专用于用户级处理。系统调用中可以阻止任意数量的goroutine,但默认情况下,只有一个可以随时执行用户级代码。它应该更聪明,而且有一天它会变得更聪明,但是如果你想要CPU并行性那么你必须告诉运行时你想要多少个goroutine同时执行代码 。有两种相关的方法可以做到这一点。使用设置为要使用的核心数的环境变量GOMAXPROCS运行您的作业,或者导入运行时包并调用runtime.GOMAXPROCS(NCPU)。一个有用的值可能是runtime.NumCPU(),它报告本地计算机上的逻辑CPU数。同样,随着调度和运行时间的改进,预计此要求将被淘汰。
最大化我的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++ {
}
}
现在实际上并没有“做”任何事情,但是看看与其他语言(如Java)编写多线程应用程序相比有多简短/简单/简单。