關於 Go1.18 新函式 TryLock 的故事
爭做團隊核心程式設計師,關注「 幽鬼 」
大家好,我是程式設計師幽鬼。
今天給大家帶來一篇關於 1.18 新函式 TryLock 故事的文章。
這篇文章基於 Go1.18。
Go 1.18 有一個新函式 TryLock
(用於互斥鎖 sync.Mutex
和 sync.RWMutex
),它允許開發人員嘗試以非阻塞模式獲取鎖,即如果鎖已經被其他人獲取,該函式將簡單地返回 false
而不是等待鎖釋放。
這個函式激起了我的好奇心,因為雖然它的名字很明確,但它的用例並不明顯。讓我們收集有關它的資訊以更好地瞭解其用法。
工作流程
為了更好地理解互斥鎖的工作流程,建議你閱讀這篇文章“ Go: Mutex and Starvation [1] ”。
在以下情況下,互斥鎖不可用:
-
該鎖當前由另一個 goroutine 持有。
-
未持有鎖,但互斥鎖處於 飢餓模式 [2] ;即,鎖將交給下一個等待者。
在以上任意一種情況下,函式 TryLock
都會立即返回 false
。這是一個總結這兩個用例的圖表:
這是一個相當快的操作,因為它只依賴於一位操作。
如果鎖可用,goroutine 將嘗試以與函式 Lock
相同的方式獲取它並返回此操作的結果。如果它不可用,goroutine 不會自旋或堵塞;這是一個完全非阻塞模式。
TryLock 解決了什麼問題?
該 函式文件 [3] 明確指出,使用此函式的情況很少見:
注意,雖然 TryLock 的正確使用確實存在,但它們很少見,並且 TryLock 的使用通常表明在特定的互斥鎖使用中存在更深層次的問題。
事實上,多年來(參見 * *2012 年的這個討論* [4] , *2013 年的這個問題* [5] ,或2013 年的 *這個其他討論 [6] ),這個功能似乎不需要甚至解決任何真正的問題,之前提到的討論都沒有帶來任何真實用例。那麼這個函式能給社群帶來什麼?實際上, 許多包 [7] 都試圖實現一個 TryLock
功能,但它們都不能與競態檢測器正確整合。至少,在官方的支援下,從原生的 race 檢測器中獲利變得更容易。
Go 標準庫和其他語言
Go 原始碼內部沒有使用這個新函式的地方。但是,Go 曾經 在 Go1.6 的 runtime 中具有類似的功能 [8] 。這用於在分析期間獲取鎖以掃描堆疊。如果執行時無法獲取鎖,則簡單地跳過跟蹤。
其他程式語言——Java:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html#tryLock、 Objective-C [9] 、 Zig [10] 和許多其他語言——實現了相同的功能。 舊版本的 JRE 實現了這個功能 [11] ,為我們提供了另一個真實的用例:鎖保護了一個負責清除佇列的功能。由於佇列可以被任何執行緒清除並且不需要多次清除,因此第一個獲得鎖的執行緒將執行任務,而其他執行緒可以恢復它們的工作。
如果您曾經使用過此功能或瞭解 Go 或其他語言的另一個用例,歡迎分享交流。
作者:Vincent Blanchon,原文連結:http://medium.com/a-journey-with-go/go-story-of-trylock-function-a69ef6dbb410
參考資料
Go: Mutex and Starvation: http://medium.com/a-journey-with-go/go-mutex-and-starvation-3f4f4e75ad50
飢餓模式: http://medium.com/a-journey-with-go/go-mutex-and-starvation-3f4f4e75ad50#16b7
函式文件: http://pkg.go.dev/sync#Mutex.TryLock
2012 年的這個討論 : http://groups.google.com/g/golang-nuts/c/MTaJNZ49u60?pli=1
2013 年的這個問題 : http://github.com/golang/go/issues/6123
*這個其他討論: http://groups.google.com/g/golang-nuts/c/vfbEGJCHGXM
許多包: http://github.com/search?l=Go&q=TryLock&type=repositories
在 Go1.6 的 runtime 中具有類似的功能: http://github.com/golang/go/blob/go1.6/src/runtime/mstkbar.go#L353
Objective-C: http://developer.apple.com/documentation/foundation/nslock/1418105-trylock?language=objc
Zig: http://github.com/ziglang/zig/blob/master/lib/std/Thread/Mutex.zig#L37
舊版本的 JRE 實現了這個功能: http://stackoverflow.com/questions/41788074/use-case-for-lock-trylock
往期推薦
歡迎關注「 幽鬼 」,像她一樣做團隊的核心。
- Go 開發人員最佳 VSCode 外掛列表
- 技巧:如何在 Go 中編寫準確的基準測試?
- 說好的 Swift 取代 Python 呢?
- 使用 Go 語言完成 HTTP 檔案上傳與下載
- 7 年後,發現用 Go 實現 CockroachDB 是正確的選擇
- 在 Golang 中使用 -w 和 -s 標誌
- 關於 Go1.18 新函式 TryLock 的故事
- Java、Go 和 Python 的多執行緒效能對比
- Go GUI 開發者調查結果
- PHP 正在迅速死去
- 為什麼基礎設施工程師更喜歡MySQL?
- 分享10個值得關注的C語言開源專案
- 60 個神級 VS Code 外掛!
- WebAssembly 開啟微服務新時代?
- 12 個優化 Docker 映象安全性的技巧
- 如何哄女神歡心,這個Go開源專案說的一清二楚
- GitHub 良心操作:推出僅供贊助者使用的儲存庫
- 程式設計師技術選型:寫Go還是Java?網友:Rust不香?
- 2021 年年度最佳開源軟體!
- Go 語言中包的風格指南