忘记解锁mutex的后果
这节,您会看到如果您忘记解锁 sync.Mutex
的后果。您将使用 forgetMutex.go
代码来做这个,把它分两部分来介绍。
forgetMutex.go
第一段代码如下:
package main
import (
"fmt"
"sync"
)
var m sync.Mutex
func function() {
m.Lock()
fmt.Println("Locked!")
}
这个程序的所有问题是由于开发者忘记释放 m sync.Mutex
互斥体的锁导致的。然而,如果您的程序只调用 function()
一次,那一切正常!
forgetMutex.go
的第二段如下:
func main() {
var w sync.WaitGroup
go func() {
defer w.Done()
function()
}()
w.Add(1)
go func() {
defer w.Done()
function()
}()
w.Add(1)
w.Wait()
}
main()
函数没有任何问题,它创建两个 goroutines 并等它们完成。
执行 forgetMutex.go
产生如下输出:
$go run forgetMutex.go
Locked!
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc42001209c)
/usr/local/Cellar/go/1.9.4/libexec/src/runtime/sema.go:56 +0x39
sync.(*WaitGroup).Wait(0xc420012090)
/usr/local/Cellar/go/1.9.4/libexec/src/sync/waitgroup.go:131 +0x72 main.main()
/Users/mtsouk/forgetMutex.go:30 +0xb6
goroutine 5 [semacquire]:
sync.runtime_SemacquireMutex(0x115c6fc, 0x0)
/usr/local/Cellar/go/1.9.4/libexec/src/runtime/sema.go:71 +0x3d
sync.(*Mutex).Lock(0x115c6f8)
/usr/local/Cellar/go/1.9.4/libexec/src/sync/mutex.go:134 +0xee main.function()
/Users/mtsouk/forgetMutex.go:11 +0x2d main.main.func1(0xc420012090)
/Users/mtsouk/forgetMutex.go:20 +0x48 created by main.main
/Users/mtsouk/forgetMutex.go:18 +0x58 exit status 2
所以,忘记解锁 sync.Mutex
互斥体会产生崩溃即使是最简单的程序。这同样适用于您将在下一节中使用的 sync.RWMutex
类型的互斥锁。