未将createJobs放入goroutine为何触发Go死锁?
直接调用createJobs触发死锁的原因分析
问题代码
package main import ( "fmt" "os" "time" ) func main() { fmt.Print("wassap") jobs := make(chan int) processStarted := make(chan struct{}, 1) processCompleted := make(chan struct{}, 1) createJobs(jobs) go func() { worker(jobs, processStarted, processCompleted) }() go func() { sync(processStarted, processCompleted) }() time.Sleep(3600 * time.Second) fmt.Print("\nend of main...") interrupt := make(chan os.Signal) <-interrupt } func createJobs(jobs chan<- int) { defer close(jobs) for i := 1; i < 20; i++ { jobs <- i } } func worker(jobs <-chan int, processStarted <-chan struct{}, processCompleted <-chan struct{}) { for { select { case i := <-jobs: fmt.Printf("\nFetching job #%d from channel", i) time.Sleep(2 * time.Second) case <-processStarted: fmt.Print("\nProcess Started. Waiting for it to be completed") <-processCompleted fmt.Print("\nProcess completed") } } } func sync(processStarted chan<- struct{}, processCompleted chan<- struct{}) { // acquire semaphore. Send signal to channel to indicate that it is busy processStarted <- struct{}{} for i := 1; i < 5; i++ { fmt.Printf("\nprocessing %d", i) time.Sleep(5 * time.Second) } // release semaphore processCompleted <- struct{}{} }
死锁原因
直接调用createJobs(jobs)时,核心问题出在无缓冲通道的阻塞特性:
jobs是无缓冲通道,无缓冲通道的发送操作必须等到有接收方准备好才能完成,否则会一直阻塞当前goroutine。- 主goroutine先执行
createJobs(jobs),此时worker和sync的goroutine还未启动,没有任何goroutine在接收jobs通道的数据。 createJobs执行到jobs <- 1时立刻阻塞,后续启动worker和sync的代码完全没有机会运行。- 此时程序只有主goroutine在运行,且它被无缓冲通道的发送操作卡死,没有其他goroutine能唤醒它,Go运行时检测到所有goroutine都处于休眠阻塞状态,就触发了死锁错误。
内容的提问来源于stack exchange,提问作者MrCujo
相关产品推荐
相关产品推荐

