Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
72 lines (55 sloc) 1.9 KB

忘记解锁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 类型的互斥锁。

You can’t perform that action at this time.