Go1.18 新特性:TryLock 是什么?需要它嗎?
大家好,我是 polarisxu。
我們知曉,Go 標(biāo)準(zhǔn)庫的 sync/Mutex、RWMutex 實(shí)現(xiàn)了 sync/Locker 接口, 提供了 Lock() 和 UnLock() 方法,可以獲取鎖和釋放鎖,我們可以方便的使用它來控制對共享資源的并發(fā)控制。(其他語言,比如 Java 是有類似 TryLock 的功能的)
- type Locker interface {
- Lock()
- Unlock()
- }
但是鎖被獲取后,在未釋放之前其他 goroutine 再調(diào)用 Lock 則會被阻塞住,這種設(shè)計(jì)在有些情況下可能不能滿足需求。有時我們希望嘗試獲取鎖,如果獲取到了則繼續(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 的負(fù)責(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.
他認(rèn)為 TryLock 會鼓勵設(shè)計(jì)者對鎖進(jìn)行不精確的思考,這可能最終會成為 race(競態(tài)) 的根源。同時,他認(rèn)為僅為 http2 提供 TryLock 不值得,希望有更具說服力的案例。
然后大家進(jìn)行了一些討論,同時 rsc 給了一個實(shí)現(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 中實(shí)現(xiàn)的三個方法。不過,rsc 建議,大家盡量別使用它。
可見,最后 rsc 妥協(xié)了,因?yàn)橛腥颂岢隽艘恍?shí)現(xiàn) TryLock 的代碼。就像 neild 說的,雖然大部分時候可能確實(shí)不需要 TryLock,但出現(xiàn)各種第三方版本的 TryLock,并非好事,而應(yīng)該有一個官方的實(shí)現(xiàn)。
看看 Mutex.TryLock 官方的實(shí)現(xiàn):https://pkg.go.dev/sync@master#Mutex.TryLock,強(qiáng)調(diào)雖然存在正確使用 TryLock 的情況,但很少見??梢姽俜绞敲銥槠潆y的添加了它。
關(guān)于 TryLock,2017 年鳥窩大佬寫過一篇文章, 如何自己實(shí)現(xiàn)一個,而且對比了幾種實(shí)現(xiàn)方式的性能,感興趣的可以閱讀:https://colobu.com/2017/03/09/implement-TryLock-in-Go/。
本文轉(zhuǎn)載自微信公眾號「polarisxu」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系polarisxu公眾號。