日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

go系列 锁的初识

發布時間:2023/12/13 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 go系列 锁的初识 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Go基礎之鎖的初識

當我們的程序就一個線程的時候是不需要用到鎖的,但是通常我們實際的代碼不會是單個線程的,所有這個時候就需要用到鎖了,那么關于鎖的使用場景主要涉及到哪些呢?

  • 當我們多個線程在讀相同的數據的時候則是需要加鎖的
  • 當我們的程序既有讀又有寫的時候更是需要加鎖的
  • 當我們有多個線程在寫的時候同樣也是需要加鎖

互斥鎖

互斥鎖:同一個時刻只有一個線程能夠拿到鎖

我們先通過一個例子來演示,如果當多個線程同時更改一個變量,結果會是怎么樣
不加鎖版本

package mainimport ("sync""fmt" )var (//lock sync.Mutexcount intw sync.WaitGroup //用于等待子線程執行完之后退出 )func main() {w.Add(1) // 在調用線程前執行w.addgo func(){for i:=0;i<100000;i++{count++}w.Done() //執行完 執行w.Done}()for i :=0;i<100000;i++{count++}w.Wait() // 最后執行w.wait等待所有的線程執行完畢fmt.Println(count)}

當我們運行多次就可以發現,最后的結果基本不可能是我們先看到的:200000
我們修改代碼代碼需要加鎖保護的地方加上鎖,并且這里加的是互斥鎖,修改后的代碼為:

package mainimport ("sync""fmt" )var (lock sync.Mutexcount intw sync.WaitGroup //用于等待子線程執行完之后退出 )func main() {w.Add(1) // 在調用線程前執行w.addgo func(){for i:=0;i<100000;i++{lock.Lock()count++lock.Unlock()}w.Done() //執行完 執行w.Done}()for i :=0;i<100000;i++{lock.Lock()count++lock.Unlock()}w.Wait() // 最后執行w.wait等待所有的線程執行完畢fmt.Println(count)}

這次當我們多次運行的時候,就能保證我們每次都能看到我們想要的值:200000
接下來看讀寫鎖

讀寫鎖

讀寫鎖主要用到讀多寫少的場景
讀寫鎖分為:讀鎖和寫鎖

如果自己設置了一個寫鎖,那么其他讀的線程以及寫的線程都拿不到鎖,這個時候和互斥鎖的功能相同
如果自己設置了一個讀鎖,那么其他寫的線程是拿不到鎖的,但是其他讀的線程都是可以拿到這個鎖

我們把上面的例子代碼進行更改:

package mainimport ("sync""fmt" ) var (rwlock sync.RWMutexw sync.WaitGroupcount int )func main() {w.Add(1)go func(){for i:=0;i<1000000;i++{rwlock.Lock() // 這里定義了一個寫鎖count++rwlock.Unlock()}w.Done()}()for i:=0;i<1000000;i++{rwlock.Lock() // 這里定義了一個寫鎖count++rwlock.Unlock()}w.Wait()fmt.Println(count) }

通過設置寫鎖,我們同樣可以實現數據的一致性
下面是一個讀鎖的使用例子:

package mainimport ("sync""fmt" )var (rwlock sync.RWMutexw sync.WaitGroupcount int )func main() {w.Add(1)go func(){for i:=0;i<1000000;i++{rwlock.Lock() // 這里定義了一個寫鎖count++rwlock.Unlock()}w.Done()}()for i:=0;i<16;i++{w.Add(1)go func(){rwlock.RLock() //這里定義了一個讀鎖fmt.Println(count)rwlock.RUnlock() //釋放讀鎖w.Done()}()}w.Wait()fmt.Println(count) }

Go中的原子操作

原子操作,我們則不需加鎖,也能保證數據的一致性
并且如果只是計算,那么原子操作則是最快的

實例代碼:

package mainimport ("sync"//"time""sync/atomic""fmt" )var (w sync.WaitGroupcount int32 )func main() {w.Add(1)//start := time.Now().UnixNano()go func() {for i:=0;i<1000000;i++{atomic.AddInt32(&count,1)}w.Done()}()for i:=0;i<1000000;i++{atomic.AddInt32(&count,1)}w.Wait()//end := time.Now().UnixNano()//fmt.Println((end- start)/1000/1000)fmt.Println(count) }

?

所有的努力都值得期許,每一份夢想都應該灌溉!

轉載于:https://www.cnblogs.com/flying1819/articles/8832749.html

總結

以上是生活随笔為你收集整理的go系列 锁的初识的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。