Go 互斥鎖和讀寫互斥鎖的實(shí)現(xiàn)
先來看這樣一段代碼,所存在的問題:
var wg sync.WaitGroup
var x int64
func main() {
wg.Add(2)
go f()
go f()
wg.Wait()
fmt.Println(x) // 輸出:12135
}
func f() {
for i:=0;i<10000;i++ {
x = x+1
}
wg.Done()
}
這里為什么輸出是 12135(不同的機(jī)器結(jié)果不一樣),而不是20000。
因?yàn)?x 的賦值,總共分為三個(gè)步驟:取出x的值、計(jì)算x的結(jié)果、給x賦值。那么由于對(duì)于f函數(shù)的調(diào)用采用了goroutine協(xié)程,所以存在資源競(jìng)爭(zhēng)的問題,所以有賦值和計(jì)算過程中存在臟數(shù)據(jù)。對(duì)于此類的問題,可以采用互斥鎖解決:
互斥鎖
互斥鎖是一種常用的控制共享資源訪問的方法,它能夠保證同時(shí)只有一個(gè)goroutine可以訪問共享資源。Go語(yǔ)言中使用sync包的Mutex類型來實(shí)現(xiàn)互斥鎖。
var wg sync.WaitGroup
var x int64
var lock sync.Mutex
func main() {
wg.Add(2)
go f()
go f()
wg.Wait()
fmt.Println(x) // 輸出:20000
}
func f() {
for i:=0;i<10000;i++ {
lock.Lock() // 加互斥鎖
x = x+1
lock.Unlock() // 解鎖
}
wg.Done()
}
使用互斥鎖能夠保證同一時(shí)間有且只有一個(gè)goroutine進(jìn)入臨界區(qū),其他的goroutine則在等待鎖;當(dāng)互斥鎖釋放后,等待的goroutine才可以獲取鎖進(jìn)入臨界區(qū),多個(gè)goroutine同時(shí)等待一個(gè)鎖時(shí),喚醒的策略是隨機(jī)的。
讀寫互斥鎖
互斥鎖是完全互斥的,但是有很多實(shí)際的場(chǎng)景下是讀多寫少的,當(dāng)我們并發(fā)的去讀取一個(gè)資源不涉及資源修改的時(shí)候是沒有必要加鎖的,這種場(chǎng)景下使用讀寫鎖是更好的一種選擇。讀寫鎖在Go語(yǔ)言中使用sync包中的RWMutex類型。
讀寫鎖分為兩種:讀鎖和寫鎖。當(dāng)一個(gè)goroutine獲取讀鎖之后,其他的goroutine如果是獲取讀鎖會(huì)繼續(xù)獲得鎖,如果是獲取寫鎖就會(huì)等待;當(dāng)一個(gè)goroutine獲取寫鎖之后,其他的goroutine無(wú)論是獲取讀鎖還是寫鎖都會(huì)等待。
var (
x1 int64
wg1 sync.WaitGroup
lock1 sync.Mutex
rwlock sync.RWMutex
)
func main() {
startTime := time.Now()
for i:=0;i<100;i++ {
wg1.Add(1)
write()
}
for i:=0;i<10000;i++ {
wg1.Add(1)
read()
}
wg1.Wait()
fmt.Println(time.Now().Sub(startTime))
// 互斥鎖用時(shí): 973.9304ms
// 讀寫互斥鎖用時(shí): 718.094ms
}
func read() {
defer wg1.Done()
//lock1.Lock() // 互斥鎖
rwlock.RLock() // 讀寫互斥鎖
fmt.Println(x1)
//lock1.Unlock() // 互斥鎖
rwlock.RUnlock() // 讀寫互斥鎖
}
func write() {
defer wg1.Done()
lock1.Lock()
x1 = x1+1
lock1.Unlock()
}
到此這篇關(guān)于Go 互斥鎖和讀寫互斥鎖的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Go 互斥鎖和讀寫互斥鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang分布式鎖簡(jiǎn)單案例實(shí)現(xiàn)流程
分布式鎖是控制分布式系統(tǒng)之間同步訪問共享資源的一種方式。如果不同的系統(tǒng)或是同一個(gè)系統(tǒng)的不同主機(jī)之間共享了一個(gè)或一組資源,那么訪問這些資源時(shí),需要通過一些互斥手段來防止彼此之間的干擾以保證一致性,在這種情況下,就需要使用分布式鎖了2022-12-12
Golang設(shè)計(jì)模式之單例模式詳細(xì)講解
單例模式很容易記住。就像名稱一樣,它只能提供對(duì)象的單一實(shí)例,保證一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問該實(shí)例的方法。本文就來聊聊Go語(yǔ)言中的單例模式,感興趣的小伙伴可以了解一下2023-01-01
一站式解決方案:在Windows和Linux上快速搭建Go語(yǔ)言開發(fā)環(huán)境
本文將介紹如何在Windows和Linux操作系統(tǒng)下搭建Go語(yǔ)言開發(fā)環(huán)境,以幫助您更高效地進(jìn)行Go語(yǔ)言開發(fā),需要的朋友可以參考下2023-10-10
詳解Go語(yǔ)言單元測(cè)試中如何解決MySQL存儲(chǔ)依賴問題
MySQL?存儲(chǔ)就是一個(gè)非常常見的外部依賴,這篇文章主要來和大家一起探討在?Go?語(yǔ)言中編寫單元測(cè)試時(shí),如何解決?MySQL?存儲(chǔ)依賴,需要的可以參考一下2023-07-07
Go語(yǔ)言同步等待組sync.WaitGroup結(jié)構(gòu)體對(duì)象方法詳解
這篇文章主要為大家介紹了Go語(yǔ)言同步等待組sync.WaitGroup結(jié)構(gòu)體對(duì)象方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08

