您的位置 首页 知识分享

Go 中 sync.Mutex 锁失效之谜:为什么在并发访问共享变量时,使用 sync.Mutex 并不能保证结果正确?

sync.mutex 锁失效之谜 在探索 go 中并发的 sync.mutex 时,一位新手遇到了令人困惑的问…

Go 中 sync.Mutex 锁失效之谜:为什么在并发访问共享变量时,使用 sync.Mutex 并不能保证结果正确?

sync.mutex 锁失效之谜

在探索 go 中并发的 sync.mutex 时,一位新手遇到了令人困惑的问题。他们编写了一个程序,目标是使用 1000 个协程对一个变量加 1000,每个协程 +1,并期待最终结果为 1000。

然而,代码执行后,却得到了随机的结果,让新手心灰意冷。问题出在哪里?

问题代码分析

var a = 0 var wg sync.waitgroup  for i := 0; i < 1000; i++ {     wg.add(1)      go func() {         defer wg.done()         var locker sync.mutex         locker.lock()         defer locker.unlock()         a++         fmt.println("a 的值为:", a)     }() }
登录后复制

新手使用的 sync.mutex 旨在控制对共享变量 a 的访问,确保同一时刻只有一个协程操作它。但是,问题在于 locker.lock() 和 locker.unlock() 被放置在匿名函数内部,而不是for循环中。

解决方案

为了解决这个问题,只需将 locker.lock() 和 locker.unlock() 移动到 for 循环中。这样,每个协程都会使用自己的 locker 对象,从而实现正确的锁定机制。

var locker sync.mutex  for i := 0; i < 1000; i++ {     wg.add(1)      go func() {         defer wg.done()         locker.lock()         defer locker.unlock()         a++         fmt.println("a 的值为:", a)     }() }
登录后复制

另一种选择是使用 atomic.addint64() 函数,它提供了一种线程安全的原子操作,可以直接对变量进行加减。

func hasLockAndWait() {     var a int64 // 使用 int64 以匹配 atomic.AddInt64()      for i := 0; i < 1000; i++ {         wg.Add(1)          go func() {             defer wg.Done()             atomic.AddInt64(&a, 1)             fmt.Println("a 的值为:", a)         }()     }      wg.Wait()     fmt.Println("a 的最终值为:", a) }
登录后复制

通过采用这些解决方案,新手应该能够获得预期的结果:变量 a 的最终值为 1000。

以上就是Go 中 sync.Mutex 锁失效之谜:为什么在共享变量时,使用 sync.Mutex 并不能保证结果正确?的详细内容,更多请关注php中文网其它相关文章!

本文来自网络,不代表甲倪知识立场,转载请注明出处:http://www.spjiani.cn/wp/4364.html

作者: nijia

发表评论

您的电子邮箱地址不会被公开。

联系我们

联系我们

0898-88881688

在线咨询: QQ交谈

邮箱: email@wangzhan.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部