golang mutex使用及注意事项
关于使用
metux的出现是为了防止资源竞争(race conditions)
调用Lock()获得锁,调用unlock()释放锁。
mutex是互斥锁。若一个goroutine获得锁,则其他goroutine会一直阻塞到他释放锁后才能获得锁。
注意事项
- 多次调用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
**/
- 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
**/
- 一个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
**/
来源:CSDN
作者:一个行走的民
链接:https://blog.csdn.net/zhaominpro/article/details/79233296