一段Go的并发锁实例程序,程序如下所示, 实现的是安全并发的去更新一个计数器的功能。整个程序输出结果与预期一致,但是问题是执行的顺序:感觉输出结果与预料的不太一样,而且加锁的顺序也跟预期不一致。
```go
var (
counter int
wg sync.WaitGroup
mutex sync.Mutex
)
func incCounter(id int) {
defer wg.Done()
for count := 0; count < 2; count++ {
mutex.Lock()
println("id=", id, " lock the mutex")
println("id=", id, " counter=", counter)
value := counter
println("id=", id, " switch to another goroutine")
runtime.Gosched()
value++
counter = value
mutex.Unlock()
println("id=", id, " unlock the mutex")
}
}
func main() {
runtime.GOMAXPROCS(2)
wg.Add(2)
go incCounter(1)
go incCounter(2)
wg.Wait()
fmt.Printf("final counter %d\n", counter)
}
```
整个的输出如下面所示,比较奇怪的是第四行的锁,竟然在没有释放的时候再次被锁定?请各位大佬帮看下,是否哪里出了问题,还是我对于锁理解错了。 程序并发执行,所以这个输出结果不是100%如下面的一样,有一定概率出现下面的输出。
```go
➜ sync-example go run main.go
id= 2 lock the mutex
id= 2 counter= 0
id= 2 switch to another goroutine
id= 1 lock the mutex
id= 1 counter= 1
id= 1 switch to another goroutine
id= 1 unlock the mutex
id= 1 lock the mutex
id= 1 counter= 2
id= 1 switch to another goroutine
id= 1 unlock the mutex
id= 2 unlock the mutex
id= 2 lock the mutex
id= 2 counter= 3
id= 2 switch to another goroutine
id= 2 unlock the mutex
final counter 4
```
mutex.Unlock()
println("id=", id, " unlock the mutex")
unlock和输出unlock日志不是原子操作
#3
更多评论
或许只是print的位置的问题,比如id=2的goroutine实际执行了释放锁但还没有打印println(“unlock,,,”),id=1的就已经开始执行自己的流程了
#1