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

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

Susan Sarandon
发布: 2024-12-16 06:02:11
原创
838 人浏览过

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

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板