
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中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号