以下内容摘录整理自《极客时间》晁岳攀(鸟窝)的专栏——《Go 并发编程实战课》。
常见的 4 种错误场景:
- Lock/Unlock 不是成对出现
- Copy 已使用的 Mutex(Mutex是值类型,传递的时候是复制)
- 重入 (Mutex不是可重入锁)
- 死锁
补充:
死锁必要的4个条件(破坏其中一个就能避免死锁):
- 互斥: 至少一个资源是被排他性独享的,其他线程必须处于等待状态,直到资源被释放。
- 持有和等待:goroutine 持有一个资源,并且还在请求其它 goroutine
持有的资源,也就是咱们常说的“吃着碗里,看着锅里”的意思。 - 不可剥夺:资源只能由持有它的 goroutine 来释放。
- 环路等待:一般来说,存在一组等待进程,P={P1,P2,…,PN},P1 等待 P2 持有的资源,P2 等待 P3 持有的资源,依此类推,最后是 PN 等待 P1 持有的资源,这就形成了一个环路等待的死结。
可重入锁的一种实现:
通过让调用者自己传入Token,用来区分不同的goroutine。
// Token方式的递归锁