這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
本文對Go中鎖機制的進行簡單介紹
Go中鎖分為兩種:
互斥鎖
並發程式對公用資源訪問的限制最常見的就是使用互斥鎖的方式。在Go中,sync.Mutex 提供了互斥鎖的實現。
簡單使用樣本:
func main() {var mutex sync.Mutexcount := 0for r := 0; r < 50; r++ { go func() { mutex.Lock() count += 1 mutex.Unlock() }() } time.Sleep(time.Second) fmt.Println("the count is : ", count)}
當執行了 mutex.Lock()
操作後,如果有另外一個 goroutine 又執行了上鎖操作,那麼該操作被被阻塞,直到該互斥鎖恢複到解鎖狀態。
讀寫鎖
顧名思義,讀寫鎖是對讀寫操作進行加鎖。需要注意的是多個讀操作之間不存在互斥關係,這樣提高了對共用資源的訪問效率。
Go中讀寫鎖由 sync.RWMutex 提供,主要包括:
- func (rw *RWMutex) Lock()
- func (rw *RWMutex) RLock()
- func (rw *RWMutex) RLocker() Locker
- func (rw *RWMutex) RUnlock()
- func (rw *RWMutex) Unlock()
其中 Lock() 即“寫鎖定”,調用了“寫鎖定”後,不能有其他goroutine進行讀或者寫操作。 Unlock() 即“寫解鎖”,調用了“寫解鎖”後會喚醒所有因為要進行“讀鎖定(即:RLock())” 而被阻塞的 goroutine。
RLock()為“讀鎖定”,調用“讀鎖定”後,不能有其他goroutine進行寫操作,但是可以進行讀操作。RUnlock() 為“讀解鎖”,調用“讀解鎖”後,會喚醒一個因為要進行“寫鎖定”而被阻塞的goroutine。
簡單使用樣本:
package mainimport ("fmt""sync""time")func main() { var mutex sync.RWMutex arr := []int{1, 2, 3} go func() { fmt.Println("Try to lock writing operation.") mutex.Lock() fmt.Println("Writing operation is locked.") arr = append(arr, 4) fmt.Println("Try to unlock writing operation.") mutex.Unlock() fmt.Println("Writing operation is unlocked.") }() go func() { fmt.Println("Try to lock reading operation.") mutex.RLock() fmt.Println("The reading operation is locked.") fmt.Println("The len of arr is : ", len(arr)) fmt.Println("Try to unlock reading operation.") mutex.RUnlock() fmt.Println("The reading operation is unlocked.") }() time.Sleep(time.Second * 2) return}
運行以上樣本,觀察輸出結果,你將能夠比較直觀的感受到讀寫鎖的作用。
公眾號: EasyHacking
微博: EasyHacking
歡迎關注交流