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

**/

猜你喜欢

转载自blog.csdn.net/zhaominpro/article/details/79233296