golang开发中的小故事

本文通过一段Golang代码示例,深入探讨了goroutine中的无限循环与runtime.GC()之间的相互作用导致的死锁现象,揭示了Golang运行时机制中的微妙细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要记录在golang学习的过程中看到的或者自己经历的golang开发中觉得比较有意思的小故事,会持续更新

一个有趣的小细节(转载,原文在这里

先看一段代码

package main

import (
    "fmt"
    "runtime"
)

func main() {
    var i byte
    go func() {
        for i = 0; i <= 255; i++ {
        }
    }()
    fmt.Println("Dropping mic")
    // Yield execution to force executing other goroutines
    runtime.Gosched()
    runtime.GC()
    fmt.Println("Done")
}

首先来说一下结论,这段代码会卡死,毋庸置疑。总结原因总有两点,一个是goroutine中的for循环由于byte的存储设计永远不会大于255,相当于是死循环,所以一旦进入就不会自动停止;第二个原因是runtime.GC()会调用stw暂停所有的goroutine,而本文中for的goroutine永远不会停止,所以卡死(stw只会关闭空闲的p,然后等待忙碌的p)。这个点我认为跟Gosched()关系不大,事实上这句话只关系着goroutine开始的时间,因为gc在关闭goroutine时一定会切换到goroutine,或者说它暂停了mian的goroutine自动会切换到for的goroutine,所以Gosched在这里并没有特别关键的作用。

如果我们往下进一步去改造这段代码,比如在for循环里面加一句print操作,会发现这时候程序就可以正常退出了,这个是因为当io缓冲满了需要输出到stdout时会阻塞for的goroutine,此时这个goroutine就处于空闲状态了。发现这里的本质了么,就是在gc生效陷入等待以后要想办法让for暂停下来,转给io是一个方法,调用Gosched放弃CPU也是一个办法,只要让系统认为它是空闲等待或阻塞状态即可。

然后我们回归这个问题的本质,gc触发stw机制会暂停所有空闲或等待阻塞的goroutine,等待忙碌的goroutine自动完成,或自动暂停,如果不会,则陷入卡死,除了GC意外,事实上runtime.GOMAXPROCS()也会触发stw。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值