欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go并發(fā)與鎖的兩種方式該如何提效詳解

 更新時間:2022年12月27日 08:55:11   作者:機智的程序員小熊  
如果沒有鎖,在我們的項目中,可能會存在多個goroutine同時操作一個資源(臨界區(qū)),這種情況會發(fā)生競態(tài)問題(數(shù)據(jù)競態(tài)),下面這篇文章主要給大家介紹了關(guān)于Go并發(fā)與鎖的兩種方式該如何提效的相關(guān)資料,需要的朋友可以參考下

并發(fā)安全,就是多個并發(fā)體在同一段時間內(nèi)訪問同一個共享數(shù)據(jù),共享數(shù)據(jù)能被正確處理。

很多語言的并發(fā)編程很容易在同時修改某個變量的時候,因為操作不是原子的,而出現(xiàn)錯誤計算,比如一個加法運算使用中的變量被修改,而導(dǎo)致計算結(jié)果出錯,典型的像統(tǒng)計商品庫存。

個人建議只要涉及到共享變量統(tǒng)統(tǒng)使用channel,因為channel源碼中使用了互斥鎖,它是并發(fā)安全的。

我們可以不用,但不可以不了解,手中有糧心中不慌。

并發(fā)不安全的例子

數(shù)組是并發(fā)不安全的,在例子開始前我們要知道append函數(shù)的行為:長度足夠在原數(shù)組cap內(nèi)追加函數(shù),增加len,長度不夠則觸發(fā)擴容,申請新數(shù)組cap增加一倍,賦值遷移。

所以在這個過程中,僅討論擴容操作的話可能存在同時申請并賦值的情況,導(dǎo)致漏掉某次擴容增加的數(shù)據(jù)。

var s []int

func appendValue(i int) {
	s = append(s, i)
}

func main() {
	for i := 0; i < 10000; i++ { //10000個協(xié)程同時添加切片
		go appendValue(i)
	}
    time.Sleep(2)
    fmt.Println(len(s))
}

比如上例,10000 個協(xié)程同時為切片增加數(shù)據(jù),你可以嘗試運行一下,打印出來的一定不是 10000

  • 以上并發(fā)操作的同一個資源,專業(yè)名詞叫做臨界區(qū)
  • 因為并發(fā)操作存在數(shù)據(jù)競爭,導(dǎo)致數(shù)據(jù)值意外改寫,最后的結(jié)果與期待的不符,這種問題統(tǒng)稱為競態(tài)問題

常見于控制商品減庫存,控制余額增減等情況。 那么有什么辦法解決競態(tài)問題呢?

  • 互斥鎖:讓訪問某個臨界區(qū)的時候,只有一個 goroutine 可以訪問。
  • 原子操作:讓某些操作變成原子的,這個后續(xù)討論。

這兩個思路貫穿了無數(shù)的高并發(fā)/分布式方案,區(qū)別是在一個進程應(yīng)用中使用,還是借助某些第三方手段來實現(xiàn),比如中間件。獨孤九劍森羅萬象一定要牢牢記住。

互斥鎖

Go 語言中互斥鎖的用法如下:

var lock sync.Mutex //互斥鎖
lock.Lock() //加鎖
s = append(s, i)
lock.Unlock() //解鎖

在訪問臨界區(qū)的前后加上互斥鎖,就可以保證不會出現(xiàn)并發(fā)問題。

我們修改還是上一個4.7.1的例子,為其增加互斥鎖。

var s []int
var lock sync.Mutex

appendValueSafe := func(i int) {
    lock.Lock()
    s = append(s, i)
    lock.Unlock()
}

for i := 0; i < 10000; i++ { //10000個協(xié)程同時添加切片
    go appendValueSafe(i)
}
time.Sleep(2)
fmt.Println(len(s))
  • 對共享變量s的寫入操作加互斥鎖,保證同一時刻只有一個goroutine修改內(nèi)容。
  • 加鎖之后到解鎖之前的內(nèi)容,同一時刻只有一個訪問,無論讀寫。
  • 無論多少次都輸出10000,不會再出現(xiàn)競態(tài)問題。
  • 要注意:如果在寫的同時,有并發(fā)讀操作時,為了防止不要讀取到寫了一半數(shù)據(jù),需要為讀操作也加鎖。

讀寫鎖

互斥鎖是完全互斥的,并發(fā)讀沒有修改的情況下是不會有問題的,也沒有必要在并發(fā)讀的時候加鎖不然效率會變低。

用法:

rwlock sync.RWMutex
//讀鎖
rwlock.RLock()
rwlock.RUnlock()

//寫鎖
rwlock.Lock()
rwlock.Unlock()

并發(fā)讀不互斥可以同時,在一個寫鎖獲取時,其他所有鎖都等待, 口訣:讀讀不互斥、讀寫互斥、寫寫互斥。具體測算速度的代碼可以見4.7.3的源碼,感興趣的可以改下注釋位置看下效率是有很明顯的提升的。

小結(jié)

  • 學習了幾個名詞:臨界區(qū)、競態(tài)問題、互斥鎖、原子操作、讀寫鎖。
  • 互斥鎖:sync.Mutex, 讀寫鎖:sync.RWMutex 都是 sync 包的。
  • 讀寫鎖比互斥鎖效率高。

問題:只加寫鎖可以嗎?為什么?

總結(jié)

到此這篇關(guān)于Go并發(fā)與鎖的兩種方式該如何提效的文章就介紹到這了,更多相關(guān)Go并發(fā)與鎖提效內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go strconv包實現(xiàn)字符串和基本數(shù)據(jù)類型轉(zhuǎn)換的實例詳解

    Go strconv包實現(xiàn)字符串和基本數(shù)據(jù)類型轉(zhuǎn)換的實例詳解

    在Go語言(Golang)的編程實踐中,strconv包是一個非常重要的標準庫,它提供了在基本數(shù)據(jù)類型(如整型、浮點型、布爾型)和字符串之間的轉(zhuǎn)換功能,本文給大家介紹了關(guān)于Go語言字符串轉(zhuǎn)換strconv,需要的朋友可以參考下
    2024-09-09
  • golang json性能分析詳解

    golang json性能分析詳解

    json格式可以算我們?nèi)粘W畛S玫男蛄谢袷街涣?,Go語言作為一個由Google開發(fā),號稱互聯(lián)網(wǎng)的C語言的語言,自然也對JSON格式支持很好。下面這篇文章主要給大家詳細分析介紹了golang json性能的相關(guān)資料,需要的朋友可以參考下。
    2018-02-02
  • golang 切片截取參數(shù)方法詳解

    golang 切片截取參數(shù)方法詳解

    這篇文章主要介紹了golang 切片截取參數(shù)方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • Golang編程并發(fā)工具庫MapReduce使用實踐

    Golang編程并發(fā)工具庫MapReduce使用實踐

    這篇文章主要為大家介紹了Golang并發(fā)工具庫MapReduce的使用實踐,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-04-04
  • GO語言延遲函數(shù)defer用法詳解

    GO語言延遲函數(shù)defer用法詳解

    本文主要介紹了GO語言延遲函數(shù)defer用法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-03-03
  • 關(guān)于golang test緩存問題

    關(guān)于golang test緩存問題

    這篇文章主要介紹了關(guān)于golang test緩存問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • Go語言中工作池的原理與實現(xiàn)

    Go語言中工作池的原理與實現(xiàn)

    工作池是一種并發(fā)編程模式,它使用一組固定數(shù)量的工作線程來執(zhí)行任務(wù)隊列中的工作單元,本文將介紹工作池的工作原理,并通過代碼示例演示其在實際應(yīng)用中的用途,有需要的可以參考下
    2023-10-10
  • 基于context.Context的Golang?loader緩存請求放大問題解決

    基于context.Context的Golang?loader緩存請求放大問題解決

    這篇文章主要為大家介紹了基于context.Context的Golang?loader緩存請求放大解決方案,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • golang利用函數(shù)閉包實現(xiàn)簡單的中間件

    golang利用函數(shù)閉包實現(xiàn)簡單的中間件

    中間件設(shè)計模式是一種常見的軟件設(shè)計模式,它在許多編程語言和框架中被廣泛應(yīng)用,這篇文章主要為大家介紹一下golang利用函數(shù)閉包實現(xiàn)一個簡單的中間件,感興趣的可以了解下
    2023-10-10
  • golang rate令牌桶源碼分析實現(xiàn)方式

    golang rate令牌桶源碼分析實現(xiàn)方式

    這篇文章主要介紹了golang rate令牌桶源碼分析實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07

最新評論