代码很简单,如下所示:
package main
import (
"fmt"
// "sync"
"time"
)
var count = uint64(0)
//var l sync.Mutex
func add() {
for {
// l.Lock()
// fmt.Println("Start ++")
count++
// l.Unlock()
}
}
func main() {
go add()
time.Sleep(1 * time.Second)
fmt.Println("Count =", count)
}
案例:
所以...我在共享变量中的用法有问题...?我的问题:
信封:
1. go版本go1.8 linux/amd64
2. 3.10.0-123.el7.x86_64
3. CentOS Linux版本7.0.1406(核心)
最佳答案
没有任何同步,您根本无法保证。
可能有多种原因,为什么在第一种情况下您会看到“计数= 0”:
在互斥体版本中,同步原语告诉编译器:
可能还有其他线程使用该互斥锁,因此需要在解锁互斥锁之前将寄存器中的值写回内存位置。至少有人可以这样考虑。真正发生的情况是,解锁和随后的锁定操作在两个go例程之间的关系之前引入了一个发生,这可以保证,我们将看到在一个线程中的解锁操作之后,在另一个线程中的锁定操作之后,所有对变量的写入操作。 ,如go memory model locks中所述,无论如何实现。
您的版本之间的差异(仅第16行被注释/未注释)可能仅是由于运行时间所致,因为打印到终端的速度可能很慢。
对于正确的程序,您需要在主程序中 sleep 之后,在fmt.Println之前锁定互斥锁,然后再对其进行解锁。但是对输出不能有确定的期望,因为结果会因机器/操作系统/而异。
关于go - Goroutine中的变量未按预期更改,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44171945/