go - 连续两次检测同一个goroutine调用sync.Mutex.Lock()
问题描述
此代码(单线程程序)将永远无法工作:
func TestDoubleLockPanics(t *testing.T) {
var mu sync.Mutex
mu.Lock()
mu.Lock()
}
然而,当我运行这个测试时,并没有恐慌。竞争检测器不会打印出数据竞争。go vet
没有抱怨,没有日志消息,它只是永远阻塞。
(我关心的实际代码显然不是这么简单——我只是把它归结为本质。)
当持有锁的线程试图重新获取同一个锁时,有什么方法可以让 Go 大声告诉我?
解决方案
Go 的sync.Mutex
对象不会跟踪哪个 goroutine 锁定了它们。或者,换句话说,没有锁定线程:只有一个数据锁。
此外,正如上面的评论Unlock
所说,您可以从其他一些 goroutine 中解锁它们,而不是锁定它们的那个。Lock
因此,调用两次实际上是有意义的。这是一个骨架示例:
func f() {
mu.Lock()
... if this is not just an example, some code goes here ...
// now wait for g() to call mu.Unlock()
mu.Lock()
fmt.Println("we got here, so g() must have done an unlock")
mu.Unlock()
}
func g() {
... some code probably goes here too ...
mu.Unlock() // allow f() to proceed
... more code, perhaps ...
}
在这种情况下,我们不希望在f
第二次Lock
调用中出现恐慌。
您可以构建自己的递归锁或其他技术,但由于每个 goroutine 的内部 ID 是隐藏的,因此非常棘手。在这个答案的评论中有一个实现的链接Recursive locking in Go,但我从来没有使用过它,甚至没有仔细看过它。
推荐阅读
- javascript - FCM Web 转换 Android webview
- c - 不知道如何检查 C 中的输入参数
- javascript - 调用 Firebaseui start(...) 时的 preventScroll
- reactjs - Axios - 被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头
- powershell - Powershell中变量定义的文件路径内的Out-File文本输入
- python - 获取数据框列中的类型列表,跳过 NaN 单元格
- python-3.x - 将答案四舍五入到小数点后两位
- python - 如何实现区分字符串长度和该字符串中的字符的函数
- blockchain - 在连接到 Rinkby 测试网络时,它给了我错误发生不匹配
- reactjs - React Native:如何遍历 XML