golang互斥鎖 sync.Mutex
先看一段代碼
package main
import (
"fmt"
"sync"
)
var x int
var wg sync.WaitGroup
func f1() {
for i := 0; i < 20000; i++ {
x++
}
wg.Done()
}
func main() {
wg.Add(2)
go f1()
go f1()
wg.Wait()
fmt.Println(x)
}
E:\go\src\learngolang\00test>00test.exe
38289
E:\go\src\learngolang\00test>00test.exe
39420
E:\go\src\learngolang\00test>00test.exe
37269
我們執(zhí)行幾次看到其實(shí)返回的x值是不固定的隔披,因?yàn)槿骶危瑑蓚€(gè)goroutine并行執(zhí)行征冷,都會(huì)對(duì)x的值做出讀寫操作择膝,導(dǎo)致了換亂。這時(shí)我們可以對(duì)x加一個(gè)互斥鎖检激,保證同時(shí)只有一個(gè)goroutine可以訪問 共享變量(臨界區(qū))肴捉。
var mutex sync.Mutex
修改一下 f1()
func f1() {
for i := 0; i < 20000; i++ {
mutex.Lock() // 所在goroutine獲得互斥鎖之后,會(huì)阻塞其他goroutine對(duì)臨界區(qū)的訪問
x++ // Lock與Unlock直接的代碼段叫臨界區(qū)叔收,慣例來說齿穗,被保護(hù)的變量應(yīng)該再Lock()之后立即聲明
mutex.Unlock() // goroutine在結(jié)束后釋放鎖是必要的,無論以哪條路徑通過函數(shù)都需要釋放饺律,即使是在錯(cuò)誤路徑中窃页,也要記得釋放。
}
wg.Done()
}
再執(zhí)行幾下看看
E:\go\src\learngolang\00test>go build
E:\go\src\learngolang\00test>00test.exe
40000
E:\go\src\learngolang\00test>00test.exe
40000
E:\go\src\learngolang\00test>00test.exe
40000