添加响应通道后Golang并发程序出现死锁问题求助
问题分析与修复
核心死锁原因
- 未启动goroutine:你直接同步调用了
massReceiveThreadPostLikes,没有用go关键字启动新goroutine,导致该函数在主goroutine里串行执行。 - 无缓冲通道阻塞:函数执行到
ch <- threadPostLikeUser时,无缓冲通道必须有接收者才能完成发送,但主goroutine此时卡在wg.Wait(),没有代码处理通道接收,导致发送操作永久阻塞。而defer waitGroup.Done()要等发送完成后才会执行,最终wg.Wait()永远等不到完成信号,触发死锁。
修复步骤
步骤1:启动goroutine
把同步调用改成goroutine启动,让任务在新线程执行:
wg.Add(1) // 加上go关键字,启动独立goroutine执行任务 go massReceiveThreadPostLikes(username, session, posts, &wg, chLikes)
步骤2:解决通道发送阻塞问题
有两种可选方案:
方案A:使用缓冲通道
创建通道时指定缓冲大小(至少为1,匹配发送goroutine数量),这样发送操作无需等待接收者即可完成:
// 创建缓冲大小为1的通道,避免发送阻塞 chLikes := make(chan []models.ThreadPostLikeUser, 1)
后续在wg.Wait()后接收数据即可:
wg.Wait() receivedLikes := <-chLikes close(chLikes) // 处理receivedLikes数据...
方案B:启动接收goroutine
在主goroutine中单独启动一个goroutine处理通道接收,确保发送方不会阻塞:
var wg sync.WaitGroup chLikes := make(chan []models.ThreadPostLikeUser) wg.Add(1) go massReceiveThreadPostLikes(username, session, posts, &wg, chLikes) // 启动接收goroutine处理数据 go func() { for likes := range chLikes { // 在这里添加业务逻辑,比如更新supporters映射 for _, user := range likes { // supporters[user.Username] = models.Supporter{...} } } }() wg.Wait() close(chLikes) fmt.Println("finished receiving likes")
修复后完整主函数示例
func getTopLikeSupporter(username string, session Session, session1 Session) ([]models.Supporter, *string, error) { var supporters = make(map[string]models.Supporter) posts, err := getThreads(username, 2, session) if err != nil { return nil, nil, err } var wg sync.WaitGroup chLikes := make(chan []models.ThreadPostLikeUser, 1) wg.Add(1) go massReceiveThreadPostLikes(username, session, posts, &wg, chLikes) wg.Wait() threadPostLikeUsers := <-chLikes close(chLikes) // 填充supporters映射的业务逻辑... fmt.Println("finished receiving likes") return nil, nil, nil }
massReceiveThreadPostLikes函数无需修改,保持原有逻辑即可。
内容的提问来源于stack exchange,提问作者Cede
相关产品推荐
相关产品推荐

