Go多协程共享变量无法交替输出始终显示aa的原因咨询
Go协程变量捕获与调度问题解析
问题核心:协程读变量的时机晚于主goroutine赋值
你的代码场景应该是主goroutine循环给变量s赋值,同时启动多个goroutine直接打印s,问题根源在于两点:
- 协程延迟捕获变量值:Go的goroutine在创建时不会立即复制外部变量
s的当前值,而是等到它真正执行打印语句时,才会去读取s的内存值。主goroutine的循环执行速度极快,三个goroutine还没被调度执行,s就已经被修改为最后一个值aa,因此所有goroutine最终读取的都是这个结果。 - 缺乏同步机制控制执行时机:多个goroutine访问未做同步的共享变量
s时,既没有同步原语保证主goroutine的修改能及时被其他goroutine看到,也无法约束goroutine的执行时机。
为什么修改后能正常工作?
- 取消
time.Sleep注释:主goroutine每次启动goroutine后暂停极短时间,哪怕只有纳秒,也给了Go调度器足够的时间去调度刚创建的goroutine执行。这样每个goroutine能在s被修改为下一个值之前,就读取到当前的s值,从而实现交替输出。 - 传入
s的指针作为参数:当你把s的指针作为参数传入goroutine时,goroutine在启动时会立即捕获这个指针参数(虽然所有协程访问的内存地址一致,但传参动作相当于让协程绑定了当前循环周期的s状态——本质上是Go在协程启动时会复制参数的当前值,哪怕是指针,也能让协程在合适时机读到对应阶段的s值)。
关于内存地址一致的验证意义
你确认各协程访问的s内存地址一致,正好说明所有goroutine都在读取同一个共享变量,这也直接印证了之前的结论:主goroutine已经把该地址的内容修改为aa,所以所有协程最终输出的都是这个值。
内容的提问来源于stack exchange,提问作者yangchnet
相关产品推荐
相关产品推荐

