为什么 Go 中会出现文件写入阻塞的最小线程创建
在 Go 中,当 goroutine 进行阻塞调用时,通常会创建线程促进此类操作。然而,当多个 goroutine 在尝试写入文件时被阻塞时,会出现令人费解的现象。尽管存在大量 goroutine,但建立的线程数量有限。
测试代码和观察
以下测试脚本演示了此行为:
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 {} }
讽刺的是,当执行这个脚本时,只创建了少数线程,如命令:
$ cat /proc/9616/status | grep -i thread Threads: 5
解决难题
理解此行为的关键在于阻塞操作的本质。在原始测试中,文件写入完成得太快,无法触发新线程的创建。
为了说明这一点,修改了测试脚本以写入更大的数据块:
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 {} }
此修改导致创建了超过 200 个线程,如命令:
$ cat /proc/17033/status | grep -i thread Threads: 203
结论
因此,当快速执行文件写入操作时,调用的阻塞性质可能不足以触发创建多个线程。只有当阻塞操作变得更加严重时,对额外线程的需求才会变得明显,从而导致线程如预期的那样激增。
以上是当许多 Goroutine 阻塞快速文件写入时,为什么 Go 创建很少的线程?的详细内容。更多信息请关注PHP中文网其他相关文章!