程序不会打印也不会退出,为啥??

victorl · · 1170 次点击
死循环里不能啥也不干,会导致 CPU 飙升。
#1
更多评论
在写个限速的库,原本是用锁来实现的一些操作,后来改成原子操作,跑基准测试的时候发现的。试过其他语言不会这样,我想这种特殊场景暴露出goroutine调度的问题,可能是个坑。
#2
你这个写法很有趣,要想解释清楚原因,需要对Go的runtime的抢占调度机制有个清晰的认识。 你起了当前运行时可以最大并行运行的goroutine数目,然后让main goroutine sleep之后,就是你for循环中启动的那些goroutines在实际的运行,并且占满了你的cpu core数,当你在goroutine中是一个for死循环,**没有任何函数调用**。 我们知道如果是OS线程的话,OS一般是基于时间片发起抢占调度(通过中断的方式),让运行时间太长的线程调度出cpu,以保证其他线程有机会被执行。同样的go语言的runtime调度器也支持抢占调度(将运行时间过长的goroutine调度出去,避免其一直运行),但由于是在用户态发起的抢占,并不能把当前正在运行的goroutine直接中断掉,所以go runtime调度器是通过为当前正在运行的goroutine设置一个flag标志其应该被抢占了(运行时间太长的原因),然后goroutine是在**自己有函数调用**的时候,判断一下自己的抢占flag是否被set,如果被set就主动出让CPU。 所以你的代码正好抓住了go runtime调度器的缺点,你可以在你的goroutine中的for死循环中加一个fmt.Print()试验一下。
#3