von*_*aka -1 struct mutex deadlock embedding go
假设我有这两种结构:
type A struct {
Mutex sync.Mutex
i int
}
type B struct {
A
sync.Mutex
}
Run Code Online (Sandbox Code Playgroud)
现在,当我试图锁定B然后A我遇到了僵局:
var b B
b.Lock()
b.Mutex.Lock()
b.Mutex.Unlock()
b.Unlock()
Run Code Online (Sandbox Code Playgroud)
我想通了,这是与结构的互斥体的名字相关A,例如,有是,如果我将其命名为无僵局Mutexx,而不是Mutex.但我不知道为什么这很重要.有人可以解释一下这种行为吗?
死锁的原因是因为您的代码将调用Lock()相同互斥锁的方法两次,这是一个阻塞操作.
解释在于Spec:选择器:
以下规则适用于选择器:
- 对于值
x类型的T或*T其中T不是指针或接口类型,x.f表示在域或方法浅的深度T,其中有这样一个f.如果没有一个f深度最浅的选择器表达式是非法的.
这是什么意思?
在B,你嵌入了一个sync.Mutex和一个值A,并A嵌入了一个sync.Mutex.
当你写B.Mutex,这可能指的是直接嵌入B.Mutex领域(非限定类型名称作为字段名),并可以同时参考B.A.Mutex(因为A场被嵌入B),但根据上述引用的规则,这将表示在最浅的深度处的场/方法B.Mutex.
同样,b.Lock()可以参考B.Mutex.Lock()并可以参考B.A.Mutex.Lock().但是再次根据引用的规则,它将表示最浅深度的场/方法,即B.Mutex.Lock().
所以这段代码:
b.Lock()
b.Mutex.Lock()
Run Code Online (Sandbox Code Playgroud)
将调用Lock()相同的方法Mutex两次,这是struct 的嵌入B.Mutex字段B.第二个调用将阻止,因为互斥锁已被锁定.
当你重命名A.Mutex为eg A.Mutexx,然后你写:
b.Lock()
b.Mutexx.Lock()
Run Code Online (Sandbox Code Playgroud)
第一个b.Lock()呼叫是指B.Mutex.Lock(),第二个b.Mutexx.Lock()呼叫是指B.A.Mutexx.Lock()呼叫,因此它们锁定2个不同的,不同的互斥锁; 它们是独立的,因此第二个锁不会阻塞(它的互斥锁尚未锁定).
| 归档时间: |
|
| 查看次数: |
119 次 |
| 最近记录: |