重入锁定

时间:2020-01-09 10:35:52  来源:igfitidea点击:

重入锁定是一种类似于死锁和嵌套监视器锁定的情况。重入锁定也包含在"锁定"和"读/写锁定"中。

如果线程重新输入Lock,ReadWriteLock或者其他不可重入的同步器,则可能会发生重入锁定。可重入意味着已持有锁的线程可以重新获取它。 Java的同步块是可重入的。因此,以下代码可以正常工作:

public class Reentrant{

  public synchronized outer(){
    inner();
  }

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

注意,如何将" outer()"和" inner()"都声明为已同步,这在Java中等效于" synchronized(this)"块。如果线程调用outer(),则从outer()内部调用inner()是没有问题的,因为两个方法(或者块)都在同一个监视对象(" this")上同步。如果线程已经拥有监视对象上的锁,则它可以访问在同一监视对象上同步的所有块。这称为重入。线程可以重新输入已经为其持有锁的任何代码块。

以下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()"的第二次调用将被阻塞。重新进入锁定已发生。

为了避免重新进入锁定,我们有两种选择:

  • 避免编写重新输入锁定的代码
  • 使用可重入锁

以下哪种选项最适合项目,取决于具体情况。可重入锁的性能通常不如不可重入锁,并且很难实现,但这在情况下可能不是问题。无论有没有锁再入,代码是否易于实现都必须视情况而定。