Golang安全讀寫共享變量的方式詳解
1. 使用互斥鎖(Mutex)
互斥鎖(Mutex)是一種常用的同步原語,用于防止多個(gè)協(xié)程同時(shí)訪問共享資源。
package main import ( "fmt" "sync" ) var ( counter int mutex sync.Mutex ) func increment(wg *sync.WaitGroup) { defer wg.Done() mutex.Lock() counter++ mutex.Unlock() } func main() { var wg sync.WaitGroup for i := 0; i < 1000; i++ { wg.Add(1) go increment(&wg) } wg.Wait() fmt.Println("Final Counter:", counter) }
2. 使用channel
Go
語言的核心理念之一就是“不通過共享內(nèi)存來通信,而是通過通信來共享內(nèi)存”。我們可以通過創(chuàng)建一個(gè)channel
,然后通過發(fā)送和接收消息的方式來讀寫共享變量。這種方式在處理并發(fā)問題時(shí)非常有用,因?yàn)?code>channel本身就提供了安全性。
package main import ( "fmt" ) func increment(counter chan int, done chan bool) { for i := 0; i < 1000; i++ { value := <-counter value++ counter <- value } done <- true } func main() { counter := make(chan int, 1) counter <- 0 done := make(chan bool) for i := 0; i < 10; i++ { go increment(counter, done) } for i := 0; i < 10; i++ { <-done } fmt.Println("Final Counter:", <-counter) }
3. 讀寫鎖(sync.RWMutex)
如果程序中的讀操作遠(yuǎn)多于寫操作,那么使用讀寫鎖可能會(huì)比互斥鎖更有效率。讀寫鎖允許多個(gè)協(xié)程同時(shí)讀取變量,但是只允許同一時(shí)刻只有一個(gè)協(xié)程進(jìn)行寫入操作。
package main import ( "fmt" "sync" ) var ( counter int rwMutex sync.RWMutex ) func read(wg *sync.WaitGroup) { defer wg.Done() rwMutex.RLock() fmt.Println("Counter:", counter) rwMutex.RUnlock() } func write(wg *sync.WaitGroup) { defer wg.Done() rwMutex.Lock() counter++ rwMutex.Unlock() } func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go read(&wg) } for i := 0; i < 10; i++ { wg.Add(1) go write(&wg) } wg.Wait() }
4. 原子操作(sync/atomic包)
對于一些簡單的數(shù)值或者布爾類型,我們可以使用原子操作來讀寫共享變量。
package main import ( "fmt" "sync" "sync/atomic" ) var counter int64 func increment(wg *sync.WaitGroup) { defer wg.Done() atomic.AddInt64(&counter, 1) } func main() { var wg sync.WaitGroup for i := 0; i < 1000; i++ { wg.Add(1) go increment(&wg) } wg.Wait() fmt.Println("Final Counter:", counter) }
5. sync.Once
如果共享變量只需要被初始化一次,可以使用sync.Once
來確保初始化的并發(fā)安全性。
package main import ( "fmt" "sync" ) var ( once sync.Once initValue int ) func initialize() { fmt.Println("Initializing...") initValue = 42 } func doSomething() { once.Do(initialize) fmt.Println("Value:", initValue) } func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() doSomething() }() } wg.Wait() }
最后給大家推薦一個(gè)LinuxC/C++高級架構(gòu)系統(tǒng)教程的學(xué)習(xí)資源與課程,可以幫助你有方向、更細(xì)致地學(xué)習(xí)C/C++后端開發(fā),具體內(nèi)容請見 https://xxetb.xetslk.com/s/1o04uB
到此這篇關(guān)于Golang安全讀寫共享變量的方式的文章就介紹到這了,更多相關(guān)Golang安全讀寫共享變量內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文搞懂Golang 時(shí)間和日期相關(guān)函數(shù)
這篇文章主要介紹了Golang 時(shí)間和日期相關(guān)函數(shù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12golang 微服務(wù)之gRPC與Protobuf的使用
這篇文章主要介紹了golang 微服務(wù)之gRPC與Protobuf的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02Golang利用Recover進(jìn)行錯(cuò)誤處理
Golang?中的?recover?是一個(gè)鮮為人知但非常有趣和強(qiáng)大的功能,這篇文章小編就來帶大家深入了解一下在Golang中是如何利用Recover進(jìn)行錯(cuò)誤處理吧2023-12-12Go錯(cuò)誤處理之panic函數(shù)和recover函數(shù)使用及捕獲異常方法
這篇文章主要介紹了Go錯(cuò)誤處理之panic函數(shù)使用及捕獲,本篇探討了如何使用 panic 和 recover 來處理 Go 語言中的異常,需要的朋友可以參考下2023-03-03