網站首頁 編程語言 正文
引言
前面講到,在資源競爭的時候可以使用互斥鎖,保證了資源訪問的唯一性,但也降低了性能,仔細分析一下場景,如果只是讀取數據,無論多少個goroutine都是不會存在邏輯上的互斥操作的。
這里讀寫鎖?? RWMutex就應運而生了,RWMutex可以分別針對讀操作和寫操作進行上鎖和解鎖。
RWMutex同一時刻允許多個讀操作進行,但只允許一個寫操作進行,同時,在某一個寫操作進行的時候,讀操作不可進行。
讀寫鎖有很多方法
- 方法一: RLock 這個方法是讀鎖,當寫鎖存在的時候,無法加載讀鎖,只有當不存在鎖,或者只有讀鎖的時候才能使用。讀鎖可以同時加載多個,適用于多度寫少的場景。
- 方法二: RUnlock 這個方法是讀解鎖,用來撤銷單次的讀鎖操作。
- 方法三: Lock 這個方法是寫上鎖,如果在添加寫上鎖之前已經有其他的讀鎖和寫鎖了,此時,這個Lock會被阻塞,直到可以使用。
- 方法四: Unlock 這個方法是寫解鎖,如果沒有綁定寫鎖就直接寫解鎖,會引發運行時錯誤。
讀操作
下面用實際的代碼做例子,看一下讀操作:
package main import ( "fmt" "sync" "time" ) //新建一個鎖對象的指針,然后待會兒再指針中創建這個鎖的對象 var rwMutex *sync.RWMutex //為了保證 子的goroutine先執行,可以使用同步等待組wg,這里創建wg的指針類型 var wg *sync.WaitGroup func main() { rwMutex = new(sync.RWMutex) wg = new(sync.WaitGroup) wg.Add(2)//這里記得+add // 在主函數中 啟動2條goroutine go readData(1) go readData(2) wg.Wait() fmt.Println("main func end") } func readData(i int) { defer wg.Done() fmt.Println(i, "start locking!") // 給讀操作 上鎖 rwMutex.RLock() // 讀數據 fmt.Println(i, "Reading data") // 睡一下 time.Sleep(1 * time.Second) // 讀解鎖 rwMutex.RUnlock() //打印提示信息 fmt.Println(i, "Read over") }
代碼運行結果如下:
2 start locking!
2 Reading data
1 start locking!
1 Reading data
2 Read over
1 Read over
main func end
從打印結果可知,第二條goroutine先上讀鎖,然后第二條開始讀取,然后第一條上讀鎖【從這里就可以看出,因為第二條的讀鎖還沒讀解鎖,第一條的讀鎖就上了,所以這里的讀鎖并不互斥】,之后第一條開始讀取,第二條讀解鎖,第一條讀解鎖。主goroutine結束。
寫操作
package main import ( "fmt" "sync" "time" ) //新建一個鎖對象的指針,然后待會兒再指針中創建這個鎖的對象 var rwMutex *sync.RWMutex //為了保證 子的goroutine先執行,可以使用同步等待組wg,這里創建wg的指針類型 var wg *sync.WaitGroup func main() { rwMutex = new(sync.RWMutex) wg = new(sync.WaitGroup) wg.Add(4) // 在主函數中 啟動2條goroutine go readData(1) go readData(2) go writeData(3) go writeData(4) wg.Wait() fmt.Println("main func end") } func readData(i int) { defer wg.Done() fmt.Println(i, "start locking!") // 給讀操作 上鎖 rwMutex.RLock() // 讀數據 fmt.Println(i, "Reading data") // 睡一下 time.Sleep(1 * time.Second) // 讀解鎖 rwMutex.RUnlock() //打印提示信息 fmt.Println(i, "Read over") } func writeData(i int) { defer wg.Done() fmt.Println(i, " Writing Start") //寫上鎖 rwMutex.Lock() fmt.Println(i, "~~~ writing right now~~~") time.Sleep(1 * time.Second) rwMutex.Unlock() fmt.Println(i, "writing completed") }
代碼運行結果如下:
2 start locking!
2 Reading data
4 ?Writing Start
1 start locking!
3 ?Writing Start
2 Read over
4 ~~~ writing right now~~~
4 writing completed
1 Reading data
1 Read over
3 ~~~ writing right now~~~
3 writing completed
main func end
分析可知,只有在goroutine4結束寫之后goroutine3才拿到權限開始寫。
不過講真,到處都是lock 和 unlock,臨界區什么的,真的是臃腫又容易出問題。
go語言中多個協程想共享數據的時候,將會有更加優雅的處理方式。
原文鏈接:https://segmentfault.com/a/1190000041821173
相關推薦
- 2022-10-07 Android調用系統圖庫獲取圖片的方法_Android
- 2022-10-02 OpenCV黑帽運算(BLACKHAT)的使用_python
- 2022-10-04 SQL語句中的DDL類型的數據庫定義語言操作_MsSql
- 2022-05-13 hiveserver2 連接報:root is not allowed to impersonate
- 2022-04-16 Python實現杰卡德距離以及環比算法講解_python
- 2022-09-10 python實現整數序列求和_python
- 2022-04-01 Python格式化輸出之format用法詳解_python
- 2023-06-16 Golang調用FFmpeg轉換視頻流的實現_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支