You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

向Go通道发送超过8个元素为何会引发死锁?

Go通道死锁问题分析与修复

问题根源

你的代码出现死锁的核心原因是:

  • printCount goroutine会在读取到-1时退出循环,导致该goroutine终止。此时主goroutine还在继续向通道发送后续元素(3、4),而无缓冲通道的发送操作必须有接收方才能完成,没有接收方的发送会永久阻塞,最终触发死锁。
  • 原代码中用time.Sleep做同步是不可靠的,它只能延迟程序退出,无法保证所有元素都被正确处理,当元素数量超过接收goroutine的处理逻辑时必然出问题。

解决方案

下面提供两种可靠的修复方案:

方案1:用通道关闭+WaitGroup同步(推荐)

这种方式是Go中处理goroutine同步的标准做法,通过关闭通道通知接收goroutine所有元素已发送完毕,用WaitGroup等待接收逻辑完成。

package main

import (
	"fmt"
	"sync"
)

func printCount(c chan int, wg *sync.WaitGroup) {
	defer wg.Done() // 函数退出时标记WaitGroup任务完成
	// 遍历通道,直到通道被关闭
	for num := range c {
		fmt.Print(num, " ")
	}
}

func main() {
	a := []int{8, 6, 7, 5, 3, 0, 9, -1, 3, 4}
	c := make(chan int)
	var wg sync.WaitGroup

	wg.Add(1) // 注册1个等待任务
	go printCount(c, &wg)

	// 发送所有元素到通道
	for _, v := range a {
		c <- v
	}
	close(c) // 发送完毕后关闭通道,通知接收goroutine退出

	wg.Wait() // 等待接收goroutine处理完所有元素
	fmt.Println("\nEnd of main")
}

方案2:保留“遇-1停止”逻辑+信号通道

如果需要保留原逻辑中“读取到-1就停止处理”的需求,可以通过额外的信号通道通知主goroutine停止发送后续元素,避免死锁。

package main

import (
	"fmt"
	"sync"
)

func printCount(c chan int, exit chan struct{}, wg *sync.WaitGroup) {
	defer wg.Done()
	num := 0
	for num >= 0 {
		select {
		case num = <-c:
			if num >= 0 {
				fmt.Print(num, " ")
			}
		case <-exit: // 收到退出信号时直接返回
			return
		}
	}
	close(exit) // 读到-1后,关闭信号通道通知主goroutine停止发送
}

func main() {
	a := []int{8, 6, 7, 5, 3, 0, 9, -1, 3, 4}
	c := make(chan int)
	exit := make(chan struct{})
	var wg sync.WaitGroup

	wg.Add(1)
	go printCount(c, exit, &wg)

	for _, v := range a {
		select {
		case c <- v:
			if v == -1 {
				<-exit // 发送-1后,等待接收goroutine的退出信号
				break
			}
		case <-exit: // 收到退出信号后停止发送
			break
		}
	}

	wg.Wait()
	fmt.Println("\nEnd of main")
}

关键知识点

  • 无缓冲通道的发送和接收操作是同步的,必须同时有发送方和接收方才能完成,否则会阻塞。
  • 不要依赖time.Sleep做goroutine同步,应该使用sync.WaitGroup、通道关闭或信号通道这类可靠的同步机制。
  • 通道关闭是安全的通知方式,接收方可以通过range遍历或ok值判断通道是否关闭,从而优雅退出。

内容的提问来源于stack exchange,提问作者yagnik pokal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 20:40:44