golang mutex使用及注意事项

golang mutex使用及注意事项

关于使用

metux的出现是为了防止资源竞争(race conditions)
调用Lock()获得锁,调用unlock()释放锁。
mutex是互斥锁。若一个goroutine获得锁,则其他goroutine会一直阻塞到他释放锁后才能获得锁。

注意事项

  1. 多次调用Lock()函数
    使用Lock()加锁后,不能再继续对其加锁(同一个goroutine中,即:同步调用),否则会panic。只有在unlock()之后才能再次Lock()。异步调用Lock(),是正当的锁竞争。当然不会有panic了
    如下:
package mutex

import ( "sync" "fmt" ) var sum = 0 var mutex sync.Mutex func A() { mutex.Lock() fmt.Println("get the lock") B() mutex.Unlock() } func B() { mutex.Lock() fmt.Println("Hello, World") mutex.Unlock() }
package mutex

import "testing"

func TestA(t *testing.T) {
    A()
}

/** 输出: get the lock fatal error: all goroutines are asleep - deadlock! goroutine 1 [chan receive]: testing.(*T).Run(0xc42009c000, 0x533f24, 0x5, 0x53c6c0, 0x468ca6) /usr/kit/go1.9.2/src/testing/testing.go:790 +0x2fc testing.runTests.func1(0xc42009c000) /usr/kit/go1.9.2/src/testing/testing.go:1004 +0x64 testing.tRunner(0xc42009c000, 0xc42003fde0) /usr/kit/go1.9.2/src/testing/testing.go:746 +0xd0 testing.runTests(0xc42000a060, 0x5d9840, 0x1, 0x1, 0xc4200483b0) /usr/kit/go1.9.2/src/testing/testing.go:1002 +0x2d8 testing.(*M).Run(0xc42003ff18, 0xc42003ff70) /usr/kit/go1.9.2/src/testing/testing.go:921 +0x111 main.main() GoDemo/mutex/_test/_testmain.go:44 +0xdb **/

解锁后再次调用就没有什么问题了

func C() {
    mutex.Lock()
    fmt.Println("this is func C()")
    mutex.Unlock()

    B()
}

/** 在对C()做测试,输出: this is func C() Hello, World **/
  1. mutex变量并不与goroutine相关联,在一个goroutine中调用加锁Lock()后,再可以在其他goroutine中调用unlock()解锁。
func D() {
    mutex.Lock()
    fmt.Println("func D() do locked")
    go E()
    time.Sleep(time.Second)//等待E()函数执行完成
    fmt.Println("func D() done")
}

func E() {
    mutex.Unlock()
    fmt.Println("func E() do unlocked")
}

/** 在对D()做测试,输出: func D() do locked func E() do unlocked func D() done **/
  1. 一个goroutine中若是在调用Lock()之前调用了unlock(),那么会panic
/** 在上面对E()做测试,输出: panic: sync: unlock of unlocked mutex [recovered] panic: sync: unlock of unlocked mutex goroutine 5 [running]: testing.tRunner.func1(0xc42009c0f0) /usr/kit/go1.9.2/src/testing/testing.go:711 +0x2d2 panic(0x5062e0, 0x54d4d0) /usr/kit/go1.9.2/src/runtime/panic.go:491 +0x283 sync.(*Mutex).Unlock(0x5fecf8) /usr/kit/go1.9.2/src/sync/mutex.go:184 +0xc1 GoDemo/mutex.E() /home/zm/works/gocode/src/GoDemo/mutex/mutex.go:42 +0x2d GoDemo/mutex.TestE(0xc42009c0f0) /home/zm/works/gocode/src/GoDemo/mutex/mutex_test.go:18 +0x20 testing.tRunner(0xc42009c0f0, 0x53d730) /usr/kit/go1.9.2/src/testing/testing.go:746 +0xd0 created by testing.(*T).Run /usr/kit/go1.9.2/src/testing/testing.go:789 +0x2de **/
阅读更多

更多精彩内容