当前位置: 首页 > 科技观察

会诱发 Goroutine 挂起的 27 个原因

时间:2023-03-22 17:09:20 科技观察

Goroutine会挂的27个原因转载本文,请联系脑筋急转弯公众号。大家好,我是炸鱼。对于上个月读者的提问,我们学习理解了在goroutineleaks中看到的大头runtime.gopark函数,输出?。有朋友提到,虽然我们知道runtime.gopark函数的由来和内涵,但是却没有提到runtime.gopark的成因。毕竟会导致Goroutine挂掉,这是我们日常编码需要注意的。为此,我整理了笔记。今天这篇文章就和大家一起看看gopark的27个原因。为了阅读方便,我们将按分类进行讲解。Part1IdentificationMeaningwaitReasonZeroNonewaitReasonGCAssistMarkingGC辅助标记waitReasonIOWaitIOwaitwaitReasonZero:没有正式解释,从用法的角度。主要用于睡眠和锁定两种场景。waitReasonGCAssistMarking:GC辅助标记阶段会造成阻塞等待。waitReasonIOWait:当IO被阻塞等待时,例如:网络请求等。Part2IdentificationMeaningwaitReasonChanReceiveNilChanchanreceive(nilchan)waitReasonChanSendNilChanchansend(nilchan)waitReasonChanReceiveNilChan:读取未初始化的通道。waitReasonChanSendNilChan:写入未初始化的通道。PartIII标识含义waitReasonDumpingHeap转储堆waitReasonGarbageCollection垃圾回收waitReasonGarbageCollectionScan垃圾回收扫描waitReasonDumpingHeap:转储GoHeap堆时,此使用场景仅在runtime.debug期间被阻塞,这是pprof的公共收集。waitReasonGarbageCollection:垃圾回收期间,主要场景在GCMarkTermination阶段触发。waitReasonGarbageCollectionScan:垃圾回收扫描时,主要场景在GC标记(GCMark)扫描到Root阶段时触发。PartIV标识含义waitReasonPanicWaitpanicwaitwaitReasonSelectselectwaitReasonSelectNoCasesselect(nocases)waitReasonPanicWait:当主goroutine发生panic时,会被触发。waitReasonSelect:调用关键字select时触发。waitReasonSelectNoCases:调用关键字select时,如果没有case,则直接触发。PartVIdentificationMeaningwaitReasonGCAssistWaitGCassistwaitwaitwaitReasonGCSweepWaitGCsweepwaitwaitReasonGCScavengeWaitGCscavengewaitwaitReasonGCAssistWait:会触发GC辅助标记阶段的结束行为。waitReasonGCSweepWait:会触发GC清扫阶段的结束行为。waitReasonGCScavengeWait:会触发GC清理阶段的结束行为。GCScavenge主要是新空间的垃圾回收。它是一个频繁运行的快速GC,负责从新空间中清理较小的对象。PartVI标识含义waitReasonChanReceivechanreceivewaitReasonChanSendchansendwaitReasonFinalizerWaitfinalizerwaitwaitReasonChanReceive:通道上的读操作,将被触发。waitReasonChanSend:对channel的写操作,会被触发。waitReasonFinalizerWait:在终结器结束时触发。在Go程序中,可以通过调用runtime.SetFinalizer函数为对象设置终结器函数。此行为对应于由结束阶段引起的收集。PartVIIIdentificationMeaningwaitReasonForceGCIdleforcegc(idle)waitReasonSemacquiresemacquirewaitReasonSleepsleepwaitReasonForceGCIdle:当强制GC(空闲时间)结束时,会被触发。waitReasonSemacquire:信号量处理结束时触发。waitReasonSleep:将触发经典的睡眠行为。第八部分标识含义waitReasonSyncCondWaitsync.Cond.WaitwaitReasonTimerGoroutineIdletimergoroutine(idle)waitReasonTraceReaderBlockedtracereader(blocked)waitReasonSyncCondWait:结合sync.Cond使用,调用sync.Wait方法时触发。waitReasonTimerGoroutineIdle:与Timer相关,当没有timer执行任务时会触发。waitReasonTraceReaderBlocked:与Trace相关,ReadTrace会返回二进制trace数据,会阻塞直到数据可用。PartIXLogoMeaningwaitReasonWaitForGCCyclewaitingforGCcyclewaitReasonGCWorkerIdleGCworker(idle)waitReasonPreemptedpreemptedwaitReasonDebugCalldebugcallwaitReasonWaitForGCCycle:等待GC周期,会休眠导致阻塞。waitReasonGCWorkerIdle:当GCWorker空闲时,会休眠造成阻塞。waitReasonPreempted:当循环调用发生抢占时,会休眠等待调度。waitReasonDebugCall:调用GODEBUG时触发。小结今天的文章是对开头详细介绍runtime.gopark函数的文章的补充,可以了解其诱发因素。主要场景有:频道。垃圾收集(GC)。睡觉。锁定等待(Lock)。抢占。IO阻塞(IOWait)其他,如:panic、finalizer、select等。根据这些特点,我们可以拆解可能造成阻塞的原因。其实不用记住它们会造成阻塞,因为有影响控制流的因素,会导致gopark的调用。