我正在阅读Katherine Cox-Buday所著的《Go的并发性。开发者的工具和技术",作者是Katherine Cox-Buday。 我被一个非常简单的例子卡住了,这个例子是为了模拟死锁。这个片段看起来是这样的。
func main() {
var wg sync.WaitGroup
printSum := func(a, b *somevar) {
defer wg.Done()
a.mu.Lock()
defer a.mu.Unlock()
time.Sleep(1 * time.Second)
b.mu.Lock()
defer b.mu.Unlock()
fmt.Printf("sum is - %d \n", a.val + b.val)
}
var a, b somevar
a.val = 50
b.val = 300
wg.Add(2)
go printSum(&a, &b)
go printSum(&a, &b)
wg.Wait()
}
然而,当我尝试运行这个程序时,我总是得到输出。
sum is - 352
sum is - 354
在这个例子中,第二个 printSum 实例是等待 var a 的锁,只有在获得锁时才会继续执行,还是继续前进,获得 var b 的锁?这本书是2015年的,那么语言行为是否有变化,导致这个例子无效?
你的实现是错误的。死锁是由循环锁定触发的,只有当你以不同的顺序锁定两个锁时才会发生。所以,可以这样做。
go printSum(&a, &b)
go printSum(&b, &a)
当锁的顺序和上面一样时,第一个锁 printSum
会锁定 a
和第二个将锁定 b
然后他们就会等着另一把锁松开,而这是不会发生的。