Golang——死锁、互斥锁、读写锁的实现
死鎖:
- 什么是鎖呢?就是某個協程(線程)在訪問某個資源時先鎖住,防止其它協程的訪問,等訪問完畢解鎖后其他協程再來加鎖進行訪問。這和我們生活中加鎖使用公共資源相似,例如:公共衛生間。
- 死鎖是指兩個或兩個以上的進程在執行過程中,由于競爭資源或者由于彼此通信而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。此時稱系統處于死鎖狀態或系統產生了死鎖,
互斥鎖:
每個資源都對應于一個可稱為 互斥鎖的標記,這個標記用來保證在任意時刻,只能有一個協程(線程)訪問該資源。其它的協程只能等待。互斥鎖是傳統并發編程對共享資源進行訪問控制的主要手段,它由標準庫sync中的Mutex結構體類型表示。sync.Mutex類型只有兩個公開的指針方法,Lock和Unlock。Lock鎖定當前的共享資源,Unlock進行解鎖。
在使用互斥鎖時,一定要注意:對資源操作完成后,一定要解鎖,否則會出現流程執行異常,死鎖等問題,通常借助defer。鎖定后,立即使用defer語句保證互斥鎖及時解鎖。
演示:
由于添加了互斥鎖,可以按序先輸出hello再輸出 world。但這里需要我們自行創建互斥鎖,并在適當的位置對鎖進行釋放。
var mutex sync.Mutex // 定義互斥鎖變量 mutexfunc printer(str string) {mutex.Lock() // 添加互斥鎖defer mutex.Unlock() // 使用結束時解鎖for _, data := range str { // 迭代器fmt.Printf("%c", data)time.Sleep(time.Second) // 放大協程競爭效果}fmt.Println() }func person1(s1 string) {printer(s1) }func person2() {printer("world") // 調函數時傳參 }func main() {go person1("hello") // main 中傳參go person2()for {} }讀寫鎖:
互斥鎖的本質是當一個goroutine訪問的時候,其他goroutine都不能訪問。這樣在資源同步,避免競爭的同時也降低了程序的并發性能。程序由原來的并行執行變成了串行執行。其實,當我們對一個不會變化的數據只做“讀”操作的話,是不存在資源競爭的問題的。因為數據是不變的,不管怎么讀取,多少goroutine同時讀取,都是可以的。所以問題不是出在“讀”上,主要是修改,也就是“寫”。修改的數據要同步,這樣其他goroutine才可以感知到。所以真正的互斥應該是讀取和修改、修改和修改之間,讀和讀是沒有互斥操作的必要的。因此,衍生出另外一種鎖,叫做讀寫鎖。讀寫鎖可以讓多個讀操作并發,同時讀取,但是對于寫操作是完全互斥的。也就是說,當一個goroutine進行寫操作的時候,其他goroutine既不能進行讀操作,也不能進行寫操作。
- 讀寫鎖控制下的多個寫操作之間都是互斥的,并且寫操作與讀操作之間也都是互斥的。但是,多個讀操作之間不存在互斥關系。
GO中的讀寫鎖由結構體類型sync.RWMutex表示。此類型的方法集合中包含兩對方法:
一組是對寫操作的鎖定和解鎖,簡稱“寫鎖定”和“寫解鎖”:
另一組表示對讀操作的鎖定和解鎖,簡稱為“讀鎖定”與“讀解鎖”:
func (*RWMutex)RLock() func (*RWMutex)RUlock()演示:
var count int // 全局變量count var rwlock sync.RWMutex // 全局讀寫鎖 rwlockfunc read(n int) {rwlock.RLock()fmt.Printf("讀 goroutine %d 正在讀取數據...\n", n)num := countfmt.Printf("讀 goroutine %d 讀取數據結束,讀到 %d\n", n, num)defer rwlock.RUnlock() } func write(n int) {rwlock.Lock()fmt.Printf("寫 goroutine %d 正在寫數據...\n", n)num := rand.Intn(1000)count = numfmt.Printf("寫 goroutine %d 寫數據結束,寫入新值 %d\n", n, num)defer rwlock.Unlock() }func main() {for i := 0; i < 5; i++ {go read(i + 1)}for i := 0; i < 5; i++ {go write(i + 1)}for {} }總結
以上是生活随笔為你收集整理的Golang——死锁、互斥锁、读写锁的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab保存格式可以用cad打开文件
- 下一篇: SpringMVC-HandlerInt