網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
資源競(jìng)爭(zhēng)
channel 常用于并發(fā)通信,要保證并發(fā)安全,主要使用互斥鎖。在并發(fā)的過(guò)程中,當(dāng)一個(gè)內(nèi)存被多個(gè) goroutine 同時(shí)訪問(wèn)時(shí),就會(huì)產(chǎn)生資源競(jìng)爭(zhēng)的情況。這塊內(nèi)存也可以稱為共享資源。
并發(fā)時(shí)對(duì)于共享資源必然會(huì)出現(xiàn)搶占資源的情況,如果是對(duì)某資源的統(tǒng)計(jì),很可能就會(huì)導(dǎo)致結(jié)果錯(cuò)誤。為保證只有一個(gè)協(xié)程拿到資源并操作它,可以引入互斥鎖 sync.Mutex。
sync.Mutex
互斥鎖,指的是并發(fā)時(shí),在同一時(shí)刻只有一個(gè)協(xié)程執(zhí)行某段代碼,其他協(xié)程只有等待該協(xié)程執(zhí)行完成后才能繼續(xù)執(zhí)行。
var (sum int mutex sync.Mutex) func add(i int){ mutex.Lock() sum+=i mute.Unlock() }
使用 mutex 加鎖保護(hù) sum+ =i 的代碼片段,這樣這個(gè)片段區(qū)就無(wú)法同時(shí)被多個(gè)協(xié)程訪問(wèn),當(dāng)有協(xié)程進(jìn)入該片段區(qū),那其他的協(xié)程就只有等待,以此保證臨界區(qū)的并發(fā)安全。
sync.Mutex 只有 Lock()和 Unlock() 方法,它們是成對(duì)存在的,且Lock后一定要執(zhí)行Unlock進(jìn)行釋放鎖。所以可以使用 defer 語(yǔ)句釋放鎖,以保證鎖一定會(huì)被釋放。
func add(i int){ mutex.Lock() defer mutex.Unlock() sum += i }
sync.RWMutex
上面例子是對(duì) sum 寫操作時(shí)使用sync.Mutex 保證并發(fā)安全,當(dāng)多個(gè)協(xié)程進(jìn)行讀取操作時(shí),避免因并發(fā)產(chǎn)生讀取數(shù)據(jù)不正確,也是可以使用互斥鎖 sync.Mutex。
func getSum(){ mutex.Lock() defer mutex.Unlock() b:=sum return b }
多個(gè)協(xié)程 goroutine 同時(shí)讀寫的資源競(jìng)爭(zhēng)問(wèn)題解決,還需要考慮性能問(wèn)題,每次讀寫共享資源都加鎖,也會(huì)導(dǎo)致性能低。
多個(gè)協(xié)程并發(fā)進(jìn)行讀寫時(shí)會(huì)遇到以下情況:
- 寫時(shí)不能同時(shí)讀,易讀到臟數(shù)據(jù)
- 讀時(shí)不能同時(shí)寫,因?yàn)闀?huì)導(dǎo)致結(jié)果不一致
- 讀時(shí)同時(shí)寫,因數(shù)據(jù)不變,無(wú)論多少個(gè) goroutine 讀都是并發(fā)安全
使用讀寫鎖 sync.RWMutex 優(yōu)化代碼:
var mutex sync.RWMutex func readSum() int { mutex.RLock() defer mutex.RUnlock() b := sum return b }
讀寫鎖的性能比互斥鎖性能好。
sync.WaitGroup
為了能夠監(jiān)聽(tīng)所有的協(xié)程的執(zhí)行,一旦所有的goroutine 都執(zhí)行完成,程序應(yīng)當(dāng)及時(shí)退出節(jié)省時(shí)間提高性能。通過(guò)使用 sync.WaitGroup 來(lái)解決。使用步驟如下:
- 聲明一個(gè) sync.WaitGroup ,通過(guò) add 方法增加計(jì)數(shù)器值,有幾個(gè)協(xié)程就計(jì)算幾個(gè)
- 每個(gè)協(xié)程結(jié)束后就調(diào)用 Done 方法,主要是讓計(jì)數(shù)器減1
- 最后調(diào)用 Wait 方法一直等待,直到計(jì)數(shù)器為 0 時(shí),所有跟蹤的協(xié)程都執(zhí)行完畢
func run() { var wg sync.WaitGroup wg.Add(100) for i := 0; i < 100; i++ { go func() { defer wg.Done() add(10) }() } wg.Wait() }
通過(guò) sync.WaitGroup 可以很好地跟蹤協(xié)程.
sync.Once
sync.Once 作用是讓代碼只執(zhí)行一次。詳細(xì)使用是調(diào)用方法 once.Do 方法,具體實(shí)現(xiàn):
func main(){ var once sync.once oneFunc := func(){ println("once func") } once.Do(oneFunc) }
sync.Once 適用于創(chuàng)建某個(gè)對(duì)象的單例、只加載一次的資源等只執(zhí)行一次的場(chǎng)景。
sync.Cond
使用 sync.WaitGroup 主要是控制等待所有的協(xié)程都執(zhí)行完畢,才最終完成。但是當(dāng)遇到場(chǎng)景是,只有等待所有條件都準(zhǔn)備好才開(kāi)始。sync.Cond 相當(dāng)于發(fā)號(hào)施令,只有通知執(zhí)行所有的協(xié)程才可以執(zhí)行,重點(diǎn)是所有協(xié)程需等待喚醒才可以開(kāi)始。
所以 sync.Cond 具有阻塞協(xié)程和喚醒協(xié)程的功能。詳細(xì)的用法:
- 通過(guò) sync.NewCond 函數(shù)生成一個(gè) *sync.Cond,用于阻塞和喚醒協(xié)程
- 調(diào)用 cond.Wait() 方法阻塞當(dāng)前協(xié)程等待,需要注意調(diào)用 cond.Wait() 方法要加鎖
- 調(diào)用 cond.Broadcast() 后所有協(xié)程才開(kāi)始執(zhí)行
func run() { cond := sync.NewCond(&sync.Mutex{}) var wg sync.WaitGroup wg.Add(101) for i := 0; i < 100; i++ { go func(num int) { defer wg.Done() fmt.Println(num, "號(hào)正在 awaiting......") cond.L.Lock() cond.Wait() //等待所有協(xié)程準(zhǔn)備完成 fmt.Println(num, "號(hào)開(kāi)始跑……") cond.L.Unlock() }(i) } // 等待所有的協(xié)程都進(jìn)入 wait 狀態(tài) time.Sleep(2*time.Second) go func() { defer wg.Done() // 所有都準(zhǔn)備完成,開(kāi)始 cond.Broadcast() }() // 防止函數(shù)提前返回退出 wg.Wait() }
原文鏈接:https://juejin.cn/post/7127846135917445127
相關(guān)推薦
- 2022-07-16 springclud 服務(wù)與服務(wù)之間調(diào)用(提供者 接口 消費(fèi)者)
- 2022-09-05 C語(yǔ)言模擬實(shí)現(xiàn)庫(kù)函數(shù)詳解_C 語(yǔ)言
- 2022-09-25 Linux中安裝和配置Redis
- 2022-07-30 .NetCore使用過(guò)濾器實(shí)現(xiàn)登錄權(quán)限認(rèn)證的方法小結(jié)_實(shí)用技巧
- 2022-08-19 ubuntu上設(shè)置Redis開(kāi)機(jī)自啟
- 2022-03-30 python怎么使用xlwt操作excel你知道嗎_python
- 2022-12-03 設(shè)置界面開(kāi)發(fā)Preference?Library數(shù)據(jù)重建機(jī)制詳解_Android
- 2022-07-16 SpringMVC 傳遞參數(shù)
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支