我正在阅读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()
}
Figure describing how the deadlock occurs, as per the book
但是,当我尝试运行此命令时,总是得到输出。
sum is - 352
sum is - 354
在此示例中,printSum的第二个实例是否将等待对var a的锁定,并且仅在获取锁定时继续进行,否则它将继续并获取对var b的锁定?
这本书来自2015年,所以语言行为发生了变化,使示例无效吗?
最佳答案
您的实现是错误的。死锁是由循环锁定触发的,只有在您以不同顺序锁定两个锁时才会发生死锁。因此,改为这样做:
go printSum(&a, &b)
go printSum(&b, &a)
当锁定顺序如上时,第一个
printSum
将锁定a
,第二个b
将锁定ojit_code,然后他们将等待另一个锁定释放,这将永远不会发生。