首页 >后端开发 >Golang >当许多 Goroutine 阻塞快速文件写入时,为什么 Go 创建很少的线程?

当许多 Goroutine 阻塞快速文件写入时,为什么 Go 创建很少的线程?

Susan Sarandon
Susan Sarandon原创
2024-12-16 06:02:11839浏览

Why Does Go Create Few Threads When Many Goroutines Block on Fast File Writes?

为什么 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中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn