go为什么不支持可重入锁
可重入锁是什么
public class Test{
Lock lock = new Lock();
public void methodA(){
lock.lock();
...........;
methodB();
...........;
lock.unlock();
}
public void methodB(){
lock.lock();
...........;
lock.unlock();
}
}
当A方法获取lock锁去锁住一段需要做原子性操作的B方法时,如果这段B方法又需要锁去做原子性操作,那么A方法就必定要与B方法出现死锁。这种会出现问题的重入一把锁的情况,叫不可重入锁。
A方法需要等B方法执行完才能解锁,但是B方法想执行完代码又必须要lock锁来加锁。A的锁未解锁前,其他代码块无法使用此锁来加锁。这是由这个不可重入锁决定的。
为什么Go没有可重入锁
如果当你的代码需要重入锁时,那就说明你的代码有问题了,我们正常写代码时,从入口函数开始,执行的层次都是一层层往下的,如果有一个锁需要共享给几个函数,那么就在调用这几个函数的上面,直接加上互斥锁就好了,不需要在每一个函数里面都添加锁,再去释放锁。
func call(){
F()
G()
}
func F() {
mu.Lock()
... do some stuff
mu.Unlock()
}
func g() {
... do some stuff ...
}
func G() {
mu.Lock()
g()
mu.Unlock()
}
这样不仅避免了死锁,而且还对代码进行了解耦。这样的代码按照作用范围进行了分层,就像金字塔一样,上层调用下层的函数,越往上作用范围越大;各层有自己的锁。
总结:Go语言中完全没有必要使用可重入锁,如果我们发现我们的代码要使用到可重入锁了,那一定是我们写的代码有问题了,请检查代码结构,修改他!!!
在单线程的测试中,无法发现bug。可重入锁无法保护invariant,是可能导致大问题的。
使用可重入锁是一种彻彻底底的错误,它是bug的温床。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!