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

Go语言并发代码打印结果为串行不符合预期,求问题原因与解决方案

问题原因

你的代码中两个goroutine没有任何同步协调逻辑,Go运行时对goroutine的调度没有顺序保证,无同步约束时单个goroutine会连续执行完所有逻辑,才会切换到其他goroutine,所以会出现一侧输出全部打印完成后才打印另一侧的情况,和预期交替效果不符。

修复方案

要实现严格的交替打印,需要通过channel来控制两个goroutine的执行时序,每次打印完成后通知对方执行,自身阻塞等待下一轮执行信号。修复后可实现预期效果的代码如下:

package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup
	wg.Add(2)
	// 两个无缓冲channel作为执行信号量
	hiSig := make(chan struct{})
	gSig := make(chan struct{})

	// 打印偶数的goroutine
	go func() {
		defer wg.Done()
		for i := 0; i < 4; i += 2 {
			<-hiSig // 等待执行信号
			fmt.Println("hi", i)
			gSig <- struct{}{} // 通知打印奇数的goroutine执行
		}
	}()

	// 打印奇数的goroutine
	go func() {
		defer wg.Done()
		for i := 1; i < 4; i += 2 {
			<-gSig // 等待执行信号
			fmt.Println("g", i)
			if i != 3 { // 最后一轮执行不需要回发信号,避免channel泄漏
				hiSig <- struct{}{}
			}
		}
	}()

	hiSig <- struct{}{} // 触发第一次hi打印,启动交替流程
	wg.Wait()
	// 关闭channel
	close(hiSig)
	close(gSig)
}
逻辑说明
  • hiSig 和 gSig 是两个无缓冲channel,用来做两个goroutine的执行时序同步,无缓冲channel的收发操作都是阻塞的,只有收发双方都就绪时操作才会完成,刚好可以用来做执行权限的交接
  • 主协程先往hiSig发送信号,让打印hi的goroutine先执行,打印完成后往gSig发信号,通知打印g的goroutine执行,自己进入阻塞等待下一轮信号
  • 打印g的goroutine收到信号后执行打印,非最后一轮的话回发信号给hi的goroutine,循环往复直到所有内容打印完成
  • WaitGroup用来等待两个goroutine全部执行完成后再退出主协程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 22:30:05