Go1.18 新特性:TryLock 是什么?需要它嗎?
大家好,我是 polarisxu。
我們知曉,Go 標(biāo)準(zhǔn)庫的 sync/Mutex、RWMutex 實現(xiàn)了 sync/Locker 接口, 提供了 Lock() 和 UnLock() 方法,可以獲取鎖和釋放鎖,我們可以方便的使用它來控制對共享資源的并發(fā)控制。(其他語言,比如 Java 是有類似 TryLock 的功能的)
- type Locker interface {
- Lock()
- Unlock()
- }
但是鎖被獲取后,在未釋放之前其他 goroutine 再調(diào)用 Lock 則會被阻塞住,這種設(shè)計在有些情況下可能不能滿足需求。有時我們希望嘗試獲取鎖,如果獲取到了則繼續(xù)執(zhí)行,如果獲取不到,我們也不想阻塞住,而是去調(diào)用其它的邏輯,這個時候我們就想要 TryLock 方法:即嘗試獲取鎖,獲取不到也不堵塞。
這個需求,2013 年就有人提出,但官方?jīng)]有采納。2018 年又有人提出:https://github.com/golang/go/issues/27544,建議增加 TryLock,但沒有下文。直到 2021 年 4 月,有人再次提出,同時也給出了標(biāo)準(zhǔn)庫中需要的場景:https://github.com/golang/go/issues/45435。
不過,Go Team 的負責(zé)人 rsc 提出了反對的意見:
Locks are for protecting invariants. If the lock is held by someone else, there is nothing you can say about the invariant.
TryLock encourages imprecise thinking about locks; it encourages making assumptions about the invariants that may or may not be true. That ends up being its own source of races.
There are definitely locking issues in http2. Adding TryLock would let us paper over them to some extent, but even that would not be a real fix. It would be more like the better your 4-wheel-drive the farther out you get stuck.
I don't believe http2 makes a compelling case for TryLock.
他認為 TryLock 會鼓勵設(shè)計者對鎖進行不精確的思考,這可能最終會成為 race(競態(tài)) 的根源。同時,他認為僅為 http2 提供 TryLock 不值得,希望有更具說服力的案例。
然后大家進行了一些討論,同時 rsc 給了一個實現(xiàn),并提到:
sync: add Mutex.TryLock, RWMutex.TryLock, RWMutex.TryRLock
Use of these functions is almost (but not) always a bad idea.
Very rarely they are necessary, and third-party implementations (using a mutex and an atomic word, say) cannot integrate as well with the race detector as implmentations in package sync itself.
也就是現(xiàn)在 Go1.18 中實現(xiàn)的三個方法。不過,rsc 建議,大家盡量別使用它。
可見,最后 rsc 妥協(xié)了,因為有人提出了一些實現(xiàn) TryLock 的代碼。就像 neild 說的,雖然大部分時候可能確實不需要 TryLock,但出現(xiàn)各種第三方版本的 TryLock,并非好事,而應(yīng)該有一個官方的實現(xiàn)。
看看 Mutex.TryLock 官方的實現(xiàn):https://pkg.go.dev/sync@master#Mutex.TryLock,強調(diào)雖然存在正確使用 TryLock 的情況,但很少見。可見官方是勉為其難的添加了它。
關(guān)于 TryLock,2017 年鳥窩大佬寫過一篇文章, 如何自己實現(xiàn)一個,而且對比了幾種實現(xiàn)方式的性能,感興趣的可以閱讀:https://colobu.com/2017/03/09/implement-TryLock-in-Go/。
本文轉(zhuǎn)載自微信公眾號「polarisxu」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系polarisxu公眾號。