【21】重入锁死


重入锁死和死锁嵌套锁死类似的情况。 在之前有关锁以及读写锁的部分,其实也提到过重入锁死的情况。

如果线程重入进锁/读写锁或者其他不可重入的同步机制,那么就可能发生重入锁死。 重入意味着一个线程可以重复获得已经持有的锁。 Java中的synchronized同步块就是可重入的。 因此,下面这个代码是可以正常工作的:

public class Reentrant{

  public synchronized outer(){
    inner();
  }

  public synchronized inner(){
    //do something
  }
}

注意:outer()inner()都声明为synchronized,这在Java中等价于synchronized(this)。 由于两个方法实际都是由对象this上的监控器来保持同步的,所以,当某个线程调用outer()时,不会影响内部再次调用inner()的。 这就是说,当某个线程已经持有某个对象上的监控器时,此线程就可以访问此监控器下的所有同步代码块。 这就是所谓的重入。 我们先来看看一个不可重入的Lock实现:

public class Lock{

  private boolean isLocked = false;

  public synchronized void lock()
  throws InterruptedException{
    while(isLocked){
      wait();
    }
    isLocked = true;
  }

  public synchronized void unlock(){
    isLocked = false;
    notify();
  }
}

如果某个线程调用了lock()两次,而期间没有调用过unlock(),这就会导致第二次lock()调用会阻塞。这就会引发重入锁死问题。

要想避免重入锁死,可以采用以下两种方式:

  1. 业务逻辑采用不许要重新加锁的实现方案
  2. 使用可重入锁实现

实际使用时,需要结合具体情况,来采用不同的处理方案。 并不是说,可重入锁就一定比不可重入锁要好。 另外,不论选择何种方案,最终都需要充分设计,以及充分的测试。

转载于:https://my.oschina.net/roccn/blog/1576070

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值