metux的出现是为了防止资源竞争(race conditions)
调用Lock()获得锁,调用unlock()释放锁。
mutex是互斥锁。若一个goroutine获得锁,则其他goroutine会一直阻塞到他释放锁后才能获得锁。
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 **/
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 **/
/** 在上面对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 **/