fra*_*lin 9 concurrency multithreading go goroutine
正如我们在go中所知,当goroutine必须执行阻塞调用(例如系统调用)或通过cgo调用C库时,可能会创建一个线程.一些测试代码:
package main
import (
"io/ioutil"
"os"
"runtime"
"strconv"
)
func main() {
runtime.GOMAXPROCS(2)
data, err := ioutil.ReadFile("./55555.log")
if err != nil {
println(err)
return
}
for i := 0; i < 200; i++ {
go func(n int) {
for {
err := ioutil.WriteFile("testxxx"+strconv.Itoa(n), []byte(data), os.ModePerm)
if err != nil {
println(err)
break
}
}
}(i)
}
select {}
}
Run Code Online (Sandbox Code Playgroud)
当我运行它时,它没有创建很多线程.
? =99=[root /root]$ cat /proc/9616/status | grep -i thread
Threads: 5
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
我稍微修改了你的程序以输出更大的块
package main
import (
"io/ioutil"
"os"
"runtime"
"strconv"
)
func main() {
runtime.GOMAXPROCS(2)
data := make([]byte, 128*1024*1024)
for i := 0; i < 200; i++ {
go func(n int) {
for {
err := ioutil.WriteFile("testxxx"+strconv.Itoa(n), []byte(data), os.ModePerm)
if err != nil {
println(err)
break
}
}
}(i)
}
select {}
}
Run Code Online (Sandbox Code Playgroud)
然后按预期显示> 200个线程
$ cat /proc/17033/status | grep -i thread
Threads: 203
Run Code Online (Sandbox Code Playgroud)
所以我认为系统调用在原始测试中退出太快,以显示您期望的效果.
goroutine是轻量级线程,它不等同于操作系统线程。的语言规范指定它作为一个“相同的地址空间内的控制的独立并发线程”。
引用软件包的文档runtime:
GOMAXPROCS变量限制了可以同时执行用户级Go代码的操作系统线程的数量。对于代表Go代码的系统调用中可以阻止的线程数量没有限制;那些不计入GOMAXPROCS限制。
仅仅因为您启动了200个goroutine,并不意味着将为它们启动200个线程。您将GOMAXPROCS其设置为2,这意味着可以同时运行2个“活动” goroutine。如果goroutine被阻塞(例如I / O等待),则可能会禁止新线程。您没有提到测试文件有多大,您启动的goroutine可能会太快地完成写入过程。
在有效围棋博客文章将它们定义为:
之所以称它们为goroutine,是因为现有术语(线程,协程,进程等)传达了不准确的含义。goroutine有一个简单的模型:它是在同一地址空间中与其他goroutine同时执行的函数。它是轻量级的,仅比分配堆栈空间花费更多。而且堆栈从小开始,因此价格便宜,并且可以通过根据需要分配(和释放)堆存储来增长。
Goroutine被多路复用到多个OS线程上,因此,如果一个应阻塞,例如在等待I / O时,其他将继续运行。他们的设计隐藏了线程创建和管理的许多复杂性。