解析golang中的并發(fā)安全和鎖問題
1. 并發(fā)安全
package main
import (
"fmt"
"sync"
)
var (
sum int
wg sync.WaitGroup
)
func test() {
for i := 0; i < 5000000; i++ {
sum += 1
}
wg.Done()
}
func main() {
// 并發(fā)和安全鎖
wg.Add(2)
go test()
go test()
wg.Wait()
fmt.Println(sum)
}
上面的代碼中我們開啟了兩個(gè)goroutine去累加變量x的值,這兩個(gè)goroutine在訪問和修改x變量的時(shí)候就會(huì)存在數(shù)據(jù)競(jìng)爭(zhēng),導(dǎo)致最后的結(jié)果與期待的不符。
2. 互斥鎖
package main
import (
"fmt"
"sync"
)
var (
sum int
wg sync.WaitGroup
mu sync.Mutex // 定義一個(gè)互斥鎖
)
func test() {
for i := 0; i < 10000000; i++ {
// 互斥鎖它能夠保證同時(shí)只能有一個(gè)goroutine去訪問共享資源
mu.Lock()
sum += 1
mu.Unlock()
}
wg.Done()
}
func main() {
fmt.Println(mu)
// 并發(fā)和安全鎖
wg.Add(2)
go test()
go test()
wg.Wait()
fmt.Println(sum)
}
使用互斥鎖能夠保證同一時(shí)間有且只有一個(gè)goroutine進(jìn)入臨界區(qū),其他的goroutine則在等待鎖;當(dāng)互斥鎖釋放后,等待的goroutine才可以獲取鎖進(jìn)入臨界區(qū),多個(gè)goroutine同時(shí)等待一個(gè)鎖時(shí),喚醒的策略是隨機(jī)的。
3. 讀寫互斥鎖
互斥鎖是完全互斥的,但是有很多實(shí)際的場(chǎng)景下是讀多寫少的,當(dāng)我們并發(fā)的去讀取一個(gè)資源不涉及資源修改的時(shí)候是沒有必要加鎖的,這種場(chǎng)景下使用讀寫鎖是更好的一種選擇。讀寫鎖在Go語言中使用sync包中的RWMutex類型。
讀寫鎖分為兩種:讀鎖和寫鎖。當(dāng)一個(gè)goroutine獲取讀鎖之后,其他的goroutine如果是獲取讀鎖會(huì)繼續(xù)獲得鎖,如果是獲取寫鎖就會(huì)等待;當(dāng)一個(gè)goroutine獲取寫鎖之后,其他的goroutine無論是獲取讀鎖還是寫鎖都會(huì)等待。
package main
import (
"fmt"
"sync"
"time"
)
var (
x int
wg sync.WaitGroup
mu sync.Mutex // 定義一個(gè)互斥鎖
rw sync.RWMutex // 定義一個(gè)讀寫鎖,注意:只有讀多寫少的時(shí)候,讀寫鎖才能發(fā)揮其優(yōu)勢(shì)
)
func write() {
rw.Lock()
x += 1
time.Sleep(10 * time.Millisecond) // 假設(shè)寫入時(shí)間耗費(fèi)10毫秒
rw.Unlock()
wg.Done()
}
func read() {
rw.RLock()
time.Sleep(time.Millisecond)
rw.RUnlock()
wg.Done()
}
func main() {
start := time.Now()
for i := 0; i < 10; i++ {
wg.Add(1)
go write()
} // 寫耗時(shí):160毫秒左右
for i := 0; i < 1000; i++ {
wg.Add(1)
go read()
} // 讀耗時(shí):15毫秒左右
wg.Wait()
end := time.Now()
fmt.Println("執(zhí)行時(shí)間:", end.Sub(start))
}
需要注意的是讀寫鎖非常適合讀多寫少的場(chǎng)景,如果讀和寫的操作差別不大,讀寫鎖的優(yōu)勢(shì)就發(fā)揮不出來。
到此這篇關(guān)于golang中的并發(fā)安全和鎖的文章就介紹到這了,更多相關(guān)golang并發(fā)和鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang開啟mod后import報(bào)紅的簡(jiǎn)單解決方案
這篇文章主要給大家介紹了關(guān)于golang開啟mod后import報(bào)紅的簡(jiǎn)單解決方案,文中通過圖文將解決的辦法介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-01-01
Golang設(shè)計(jì)模式之外觀模式的實(shí)現(xiàn)
這篇文章主要介紹了Golang設(shè)計(jì)模式之外觀模式的實(shí)現(xiàn),外觀模式是一種常用的設(shè)計(jì)模式之一,是一種結(jié)構(gòu)型設(shè)計(jì)模式,它提供了一個(gè)簡(jiǎn)單的接口來訪問復(fù)雜系統(tǒng)的各種功能,從而降低了系統(tǒng)的復(fù)雜度,需要詳細(xì)了解可以參考下文2023-05-05
如何使用go實(shí)現(xiàn)創(chuàng)建WebSocket服務(wù)器
文章介紹了如何使用Go語言和gorilla/websocket庫創(chuàng)建一個(gè)簡(jiǎn)單的WebSocket服務(wù)器,并實(shí)現(xiàn)商品信息的實(shí)時(shí)廣播,感興趣的朋友一起看看吧2024-11-11
解決golang post文件時(shí)Content-Type出現(xiàn)的問題
這篇文章主要介紹了解決golang post文件時(shí)Content-Type出現(xiàn)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-05-05

