這篇文章給大家分享的是有關Go 并發(fā)編程之 Mutex是什么的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。
成都創(chuàng)新互聯(lián)公司主要從事成都網(wǎng)站設計、成都網(wǎng)站建設、網(wǎng)頁設計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務。立足成都服務揚州,10多年網(wǎng)站建設經(jīng)驗,價格優(yōu)惠、服務專業(yè),歡迎來電咨詢建站服務:18982081108
我們比較常見的大型項目的設計中都會出現(xiàn)并發(fā)訪問問題,并發(fā)就是為了解決數(shù)據(jù)的準確性,保證同一個臨界區(qū)的數(shù)據(jù)只能被一個線程進行操作,日常中使用到的并發(fā)場景也是很多的:
上面都是并發(fā)帶來的數(shù)據(jù)準確性的問題,決絕方案就是使用互斥鎖,也就是今天并發(fā)編程中的所要描述的 Mutex 并發(fā)原語。
互斥鎖 Mutex 就是為了避免并發(fā)競爭建立的并發(fā)控制機制,其中有個“臨界區(qū)”的概念。
在并發(fā)編程過程中,如果程序中一部分資源或者變量會被并發(fā)訪問或者修改,為了避免并發(fā)訪問導致數(shù)據(jù)的不準確,這部分程序需要率先被保護起來,之后操作,操作結(jié)束后去除保護,這部分被保護的程序就叫做臨界區(qū)。
使用互斥鎖,限定臨界區(qū)只能同時由一個線程持有,若是臨界區(qū)此時被一個線程持有,那么其他線程想進入到這個臨界區(qū)的時候,就會失敗或者等待釋放鎖,持有此臨界區(qū)的線程退出,其他線程才有機會獲得這個臨界區(qū)。
go mutex 臨界區(qū)示意圖
Mutex 是 Go 語言中使用最廣泛的同步原語,也稱為并發(fā)原語,解決的是并發(fā)讀寫共享資源,避免出現(xiàn)數(shù)據(jù)競爭 data race 問題。
互斥鎖 Mutex 提供了兩個方法 Lock 和 Unlock:進入到臨界區(qū)使用 Lock 方法加鎖,退出臨界區(qū)使用 Unlock 方法釋放鎖。
type Locker interface { Lock() Unlock()}func(m *Mutex)Lock()func(m *Mutex)Unlock()
當一個 goroutine 調(diào)用 Lock 方法獲取到鎖后,其他 goroutine 會阻塞在 Lock 的調(diào)用上,直到當前獲取到鎖的 goroutine 釋放鎖。
接下來是一個計數(shù)器的例子,是由 100 個 goroutine 對計數(shù)器進行累加操作,最后輸出結(jié)果:
package mainimport ( "fmt" "sync")func main() { var mu sync.Mutex countNum := 0 // 確認輔助變量是否都執(zhí)行完成 var wg sync.WaitGroup // wg 添加數(shù)目要和 創(chuàng)建的協(xié)程數(shù)量保持一致 wg.Add(100) for i := 0; i < 100; i++ { go func() { defer wg.Done() for j := 0; j < 1000; j++ { mu.Lock() countNum++ mu.Unlock() } }() } wg.Wait() fmt.Printf("countNum: %d", countNum)}
很多時候 Mutex 并不是單獨使用的,而是嵌套在 Struct 中使用,作為結(jié)構(gòu)體的一部分,如果嵌入的 struct 有多個字段,我們一般會把 Mutex 放在要控制的字段上面,然后使用空格把字段分隔開來。
甚至可以把獲取鎖、釋放鎖、計數(shù)加一的邏輯封裝成一個方法。
package mainimport ( "fmt" "sync")// 線程安全的計數(shù)器type Counter struct { CounterType int Name string mu sync.Mutex count uint64}// 加一方法func (c *Counter) Incr() { c.mu.Lock() defer c.mu.Unlock() c.count++}// 取數(shù)值方法 線程也需要受保護func (c *Counter) Count() uint64 { c.mu.Lock() defer c.mu.Unlock() return c.count}func main() { // 定義一個計數(shù)器 var counter Counter var wg sync.WaitGroup wg.Add(100) for i := 0; i < 100; i++ { go func() { defer wg.Done() for j := 0; j < 1000; j++ { counter.Incr() } }() } wg.Wait() fmt.Printf("%d\n", counter.Count())}
感謝各位的閱讀!關于Go 并發(fā)編程之 Mutex是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!