Hello! 欢迎来到小浪资源网!


GO:缺乏同步


GO:缺乏同步

var a string var done bool  func setup() {     a = "hello, world"     done = true }  func doprint() {     if !done {         once.do(setup)     }     print(a) }  func twoprint() {     go doprint()     go doprint() } 

代码分析

变量:

功能:

  • f():
    • 顺序写入 a 和 b(a = 1 且 b = 2)。
  • g():
  • 读取并打印 b,然后打印 a。

main() 中的并发

  • 函数 f() 使用 go f() 作为单独的 goroutine 执行。
  • 函数 g() 直接在主 goroutine 中执行。

潜在问题:

  • 运行 f() 的 goroutine 和执行 g() 的主 goroutine 并发运行。
  • 在 g() 读取并打印 a 和 b 的值之前,f() 中对 a 和 b 的写入可能无法完成。
  • 这引入了数据竞争,其中并发访问(在 f() 中写入并在 g() 中读取)发生在共享内存(a 和 b)上,而无需同步。

可能的结果
由于缺乏同步,程序的输出是不确定的。以下是可能的情况:

情况 1:g() 在 f() 修改 a 和 b 之前执行:

  • a 和 b 的初始值为 0(go 中未初始化 int 的默认值)。
0 0  

情况 2:如果 b = 2 在 g() 之前完成,但 a = 1 未完成,则输出可能为:

2 0 

主要观察结果
数据竞争:在不同步的情况下对 a 和 b 进行并发访问会引入数据竞争。这使得程序的行为变得不确定且不可预测

修复代码

  1. 使用sync.waitgroup: 确保 f() 在 g() 执行之前完成
var a, b int var wg sync.waitgroup  func f() {     a = 1     b = 2     wg.done() }  func g() {     print(b)     print(a) }  func main() {     wg.add(1)     go f()     wg.wait()     g() }  
  1. 使用频道: 当 f() 完成时发出信号:
var a, b int  func f(done chan bool) {     a = 1     b = 2     done <- true }  func g() {     print(b)     print(a) }  func main() {     done := make(chan bool)     go f(done)     <-done     g() }  

这里,g() 等待,直到 f() 通过完成的通道发送信号。

相关阅读