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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Golang 原子操作与互斥锁

發布時間:2023/12/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Golang 原子操作与互斥锁 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Golang 原子操作與互斥鎖

先來看一個代碼

package mainimport ("fmt""runtime""sync" )var (counter int32wg sync.WaitGroup )func main() {wg.Add(2) // 設置需要等待的 goroutine 的數量為 2go addCounter("Gerald")go addCounter("Seligman")wg.Wait()fmt.Println("Final Counter is: %+v", counter) }func addCounter(whoAmI string) {defer wg.Done()for count := 0; count < 2; count++ {value := counter// Gosched使當前go程放棄處理器,以讓其它go程運行。它不會掛起當前go程,因此當前go程未來會恢復執行。runtime.Gosched()value++counter = value} }

Final Counter is: 2

首先這個程序是起了兩個 goroutine 。每個 goroutine 都對 counter 進行了兩次累加操作,所以理論上 counter 最后應該是 4 而不是 2 。

原因是因為,Gerald 協程獲取到 counter 的值后,又讓 Seligman 協程去獲取 counter 的值。注意此時 counter 的值還沒改變,所以他們兩個協程都拿到 0 這個值。然后兩個協程又將 value++ 后賦值給 counter,等于說做了兩次 counter = 1 的操作。第二次循環也是一樣的原理。所以最后的值是 2 。

這種情況可以用兩中方式避免

  • Atomic 原子操作
  • Mutex 互斥鎖

Atomic

for count := 0; count < 2; count++ {value := counter// Gosched使當前go程放棄處理器,以讓其它go程運行。它不會掛起當前go程,因此當前go程未來會恢復執行。runtime.Gosched()value++counter = value}

這段代碼其實有點奇怪,為什么給 counter + 1 要寫得這么多步。這其實是在模擬 CPU 內部再給你個值+1的時候需要做的操作。首先寄存器會把 counter 的值拿出來保存在寄存器里,然后在寄存器里進行+1操作,最后再把寄存器里的值放到CPU里(原理是這樣,若位置錯誤,請及時提醒,見諒)。

而 Atomic 就是相當于在 CPU 里加鎖,讓這三步操作在執行的時候,當前協程不可以被調度切換,等這三步完成之后才可以被調度切換。

package mainimport ("fmt""runtime""sync""sync/atomic" )var (counter int32wg sync.WaitGroup )func main() {wg.Add(2) // 設置需要等待的 goroutine 的數量為 2go addCounter("Gerald")go addCounter("Seligman")wg.Wait()fmt.Println("Final Counter is: ", counter) }func addCounter(whoAmI string) {defer wg.Done()for count := 0; count < 2; count++ {//value := counter// Gosched使當前go程放棄處理器,以讓其它go程運行。它不會掛起當前go程,因此當前go程未來會恢復執行。//runtime.Gosched()////value++////counter = valueatomic.AddInt32(&counter, 1)runtime.Gosched()} }

Final Counter is: 4

這次 counter 就變成 4 了,符合預期。

Mutex

這個應該很熟悉了,互斥鎖,就是在對元素操作之前進行加鎖,操作完了解鎖。就可以保證數據一致了。

package mainimport ("fmt""sync" )var (counter int32wg sync.WaitGroupmutex sync.Mutex )func main() {wg.Add(2) // 設置需要等待的 goroutine 的數量為 2go addCounter("Gerald")go addCounter("Seligman")wg.Wait()fmt.Println("Final Counter is: ", counter) }func addCounter(whoAmI string) {defer wg.Done()for count := 0; count < 2; count++ {//value := counter// Gosched使當前go程放棄處理器,以讓其它go程運行。它不會掛起當前go程,因此當前go程未來會恢復執行。//runtime.Gosched()////value++////counter = value//atomic.AddInt32(&counter, 1)//runtime.Gosched()mutex.Lock()counter++mutex.Unlock()} }

Final Counter is: 4

叮~🔔

總結

以上是生活随笔為你收集整理的Golang 原子操作与互斥锁的全部內容,希望文章能夠幫你解決所遇到的問題。

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