中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

golang并發安全及鎖怎么實現

發布時間:2022-04-14 15:20:14 來源:億速云 閱讀:123 作者:iii 欄目:開發技術

本文小編為大家詳細介紹“golang并發安全及鎖怎么實現”,內容詳細,步驟清晰,細節處理妥當,希望這篇“golang并發安全及鎖怎么實現”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

并發安全和鎖

有時候在Go代碼中可能會存在多個goroutine同時操作一個資源(臨界區),這種情況會發生競態問題(數據競態)。類比現實生活中的例子有十字路口被各個方向的的汽車競爭;還有火車上的衛生間被車廂里的人競爭。

舉個例子:

var x int64
var wg sync.WaitGroup
func add() {
    for i := 0; i < 5000; i++ {
        x = x + 1
    }
    wg.Done()
}
func main() {
    wg.Add(2)
    go add()
    go add()
    wg.Wait()
    fmt.Println(x)
}

上面的代碼中我們開啟了兩個goroutine去累加變量x的值,這兩個goroutine在訪問和修改x變量的時候就會存在數據競爭,導致最后的結果與期待的不符。

互斥鎖

import (
	"fmt"
	"sync"
)
var lock sync.Mutex
lock.Lock() // 加鎖
lock.Unlock() // 解鎖

互斥鎖是一種常用的控制共享資源訪問的方法,它能夠保證同時只有一個goroutine可以訪問共享資源。Go語言中使用sync包的Mutex類型來實現互斥鎖。 使用互斥鎖來修復上面代碼的問題:

var x int64
var wg sync.WaitGroup
var lock sync.Mutex
func add() {
    for i := 0; i < 5000; i++ {
        lock.Lock() // 加鎖
        x = x + 1
        lock.Unlock() // 解鎖
    }
    wg.Done()
}
func main() {
    wg.Add(2)
    go add()
    go add()
    wg.Wait()
    fmt.Println(x)
}

使用互斥鎖能夠保證同一時間有且只有一個goroutine進入臨界區,其他的goroutine則在等待鎖;當互斥鎖釋放后,等待的goroutine才可以獲取鎖進入臨界區,多個goroutine同時等待一個鎖時,喚醒的策略是隨機的。

讀寫互斥鎖

import (
	"fmt"
	"sync"
)
var rwlock sync.RWMutex
rwlock.Lock()   // 加寫鎖
rwlock.Unlock() // 解寫鎖

互斥鎖是完全互斥的,但是有很多實際的場景下是讀多寫少的,當我們并發的去讀取一個資源不涉及資源修改的時候是沒有必要加鎖的,這種場景下使用讀寫鎖是更好的一種選擇。讀寫鎖在Go語言中使用sync包中的RWMutex類型。

讀寫鎖分為兩種:讀鎖和寫鎖。當一個goroutine獲取讀鎖之后,其他的goroutine如果是獲取讀鎖會繼續獲得鎖,如果是獲取寫鎖就會等待;當一個goroutine獲取寫鎖之后,其他的goroutine無論是獲取讀鎖還是寫鎖都會等待。

讀寫鎖示例:

var (
    x      int64
    wg     sync.WaitGroup
    lock   sync.Mutex
    rwlock sync.RWMutex
)
func write() {
    // lock.Lock()   // 加互斥鎖
    rwlock.Lock() // 加寫鎖
    x = x + 1
    time.Sleep(10 * time.Millisecond) // 假設讀操作耗時10毫秒
    rwlock.Unlock()                   // 解寫鎖
    // lock.Unlock()                     // 解互斥鎖
    wg.Done()
}
func read() {
    // lock.Lock()                  // 加互斥鎖
    rwlock.RLock()               // 加讀鎖
    time.Sleep(time.Millisecond) // 假設讀操作耗時1毫秒
    rwlock.RUnlock()             // 解讀鎖
    // lock.Unlock()                // 解互斥鎖
    wg.Done()
}
func main() {
    start := time.Now()
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go write()
    }

    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go read()
    }
    wg.Wait()
    end := time.Now()
    fmt.Println(end.Sub(start))
}

需要注意的是讀寫鎖非常適合讀多寫少的場景,如果讀和寫的操作差別不大,讀寫鎖的優勢就發揮不出來。

讀到這里,這篇“golang并發安全及鎖怎么實現”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

平乐县| 安多县| 洪泽县| 额济纳旗| 寿阳县| 长治市| 晋江市| 定结县| 志丹县| 株洲市| 吴桥县| 高要市| 汕尾市| 宁夏| 枞阳县| 阳谷县| 壤塘县| 宁强县| 腾冲县| 通江县| 万山特区| 洛川县| 泸定县| 贵港市| 德兴市| 尼玛县| 山东省| 奎屯市| 神农架林区| 咸丰县| 嘉定区| 万山特区| 阜平县| 鸡泽县| 临颍县| 那坡县| 安宁市| 濮阳市| 高淳县| 三门县| 镇巴县|