Go語言實戰筆記(十七)| Go 讀寫鎖

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

《Go語言實戰》讀書筆記,未完待續,歡迎掃碼關注公眾號flysnow_org或者網站http://www.flysnow.org/,第一時間看後續筆記。覺得有協助的話,順手分享到朋友圈吧,感謝支援。

前面的有篇文章在講資源競爭的時候,講互斥鎖,互斥鎖的根本就是當一個goroutine訪問的時候,其他goroutine都不能訪問,這樣肯定保證了資源的同步,避免了競爭,不過也降低了效能。

仔細剖析我們的情境,當我們讀取一個資料的時候,如果這個資料永遠不會被修改,那麼其實是不存在資源競爭的問題的,因為資料是不變的,不管怎麼讀取,多少goroutine同時讀取,都是可以的。

所以其實讀取並不是問題,問題主要是修改,修改的資料要同步,這樣其他goroutine才可以感知到。所以真正的互斥應該是讀取和修改、修改和修改之間,讀取和讀取是沒有互斥操作的。

所以這就延伸出來另外一種鎖,叫做讀寫鎖。

讀寫鎖可以讓多個讀操作同時並發,同時讀取,但是對於寫操作是完全互斥的。也就是說,當一個goroutine進行寫操作的時候,其他goroutine既不能進行讀操作,也不能進行寫操作。

1234567891011121314151617181920212223242526272829303132333435
var count intvar wg sync.WaitGroupfunc main() {wg.Add(10)for i:=0;i<5;i++ {go read(i)}for i:=0;i<5;i++ {go write(i);}wg.Wait()}func read(n int) {fmt.Printf("讀goroutine %d 正在讀取...\n",n)v := countfmt.Printf("讀goroutine %d 讀取結束,值為:%d\n", n,v)wg.Done()}func write(n int) {fmt.Printf("寫goroutine %d 正在寫入...\n",n)v := rand.Intn(1000)count = vfmt.Printf("寫goroutine %d 寫入結束,新值為:%d\n", n,v)wg.Done()}

以上我們定義了一個共用的資源count,並且聲明了2個函數進行讀寫readwrite,在main函數的測試中,我們同時啟動了5個讀寫goroutine進行讀寫操作,通過列印的結果來看,寫入操作是處於競爭狀態的,有的寫入操作被覆蓋了。通過go build -race也可以看到更明細的競爭態。

針對這種情況,第一個方案是加互斥鎖,同時智能有一個goroutine可以操作count,但是這種方法效能比較慢,而且我們說的讀操作可以不互斥,所以這種情況比較適合使用讀寫鎖。

12345678910111213141516171819202122232425262728293031323334353637383940
var count intvar wg sync.WaitGroupvar rw sync.RWMutexfunc main() {wg.Add(10)for i:=0;i<5;i++ {go read(i)}for i:=0;i<5;i++ {go write(i);}wg.Wait()}func read(n int) {rw.RLock()fmt.Printf("讀goroutine %d 正在讀取...\n",n)v := countfmt.Printf("讀goroutine %d 讀取結束,值為:%d\n", n,v)wg.Done()rw.RUnlock()}func write(n int) {rw.Lock()fmt.Printf("寫goroutine %d 正在寫入...\n",n)v := rand.Intn(1000)count = vfmt.Printf("寫goroutine %d 寫入結束,新值為:%d\n", n,v)wg.Done()rw.Unlock()}

我們在read裡使用讀鎖,也就是RLockRUnlock,寫鎖的方法名和我們平時使用的一樣LockUnlock,這樣,我們就使用了讀寫鎖,可以並發的讀,但是同時只能有一個寫,並且寫的時候不能進行讀操作,現在我們再運行代碼,可以從輸出的資料看到,可以獨到新值了。

我們同時也可以使用go build -race 檢測,也沒有競爭提示了。

《Go語言實戰》讀書筆記,未完待續,歡迎掃碼關注公眾號flysnow_org或者網站http://www.flysnow.org/,第一時間看後續筆記。覺得有協助的話,順手分享到朋友圈吧,感謝支援。

我們在做Java開發的時候,肯定知道SynchronizedMap這個Map,它是一個在多線程下安全的Map,我們可以通過Collections.synchronizedMap(Map<K, V>)來擷取一個安全的Map,下面我們看看如何使用讀寫鎖,基於Go語言來實現一個安全的Map 。

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
package commonimport ("sync")//安全的Maptype SynchronizedMap struct {rw *sync.RWMutexdata map[interface{}]interface{}}//儲存操作func (sm *SynchronizedMap) Put(k,v interface{}){sm.rw.Lock()defer sm.rw.Unlock()sm.data[k]=v}//擷取操作func (sm *SynchronizedMap) Get(k interface{}) interface{}{sm.rw.RLock()defer sm.rw.RUnlock()return sm.data[k]}//刪除操作func (sm *SynchronizedMap) Delete(k interface{}) {sm.rw.Lock()defer sm.rw.Unlock()delete(sm.data,k)}//遍曆Map,並且把遍曆的值給回呼函數,可以讓調用者控製做任何事情func (sm *SynchronizedMap) Each(cb func (interface{},interface{})){sm.rw.RLock()defer sm.rw.RUnlock()for k, v := range sm.data {cb(k,v)}}//產生初始化一個SynchronizedMapfunc NewSynchronizedMap() *SynchronizedMap{return &SynchronizedMap{rw:new(sync.RWMutex),data:make(map[interface{}]interface{}),}}

這個安全的Map被我們定義為一個SynchronizedMap的結構體,這個結構體裡有兩個欄位,一個是讀寫鎖rw,一個是儲存資料的datadata是map類型。

然後就是給SynchronizedMap定義一些方法,如果這些方法是增刪改的,就要使用寫鎖,如果是唯讀,就使用讀鎖,這樣就保證了我們資料data在多個goroutine下的安全性。

有了這個安全的Map我們就可以在多goroutine下增刪改查資料了,都是安全的。

這裡定義了一個Each方法,這個方法很有意思,用過Gradle的都知道,也有類似遍曆Map的方法。這個方法我們可以傳入一個回呼函數作為參數,來對我們遍曆的SynchronizedMap資料進行處理,比如我列印SynchronizedMap中的資料。

123
sm.Each(func(k interface{}, v interface{}) {fmt.Println(k," is ",v)})

sm就是一個SynchronizedMap,非常簡潔吧。

以上就是讀寫鎖使用的一個例子,我們可以把這個map資料當成快取資料,或者當成資料庫,然後使用讀寫鎖進行控制,可以多讀,但是只能有一個寫。

《Go語言實戰》讀書筆記,未完待續,歡迎掃碼關注公眾號flysnow_org或者網站http://www.flysnow.org/,第一時間看後續筆記。覺得有協助的話,順手分享到朋友圈吧,感謝支援。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.