[Lock] What is reentrant lock

I believe we often hear the concept of re-entry lock at work or in the interview process, or contrast with the keyword synchrozied stack long interview so many people, 80 percent of interviewees did not answer or no answer on the point, or the double lock efficacy confused, dumbfounding. .

So how much do you have to re-enter the lock understand it? Today, the stack length to help you tear reentrant lock veil, to experience the true face under reentrant lock. .

What is reentrant lock

java.util.concurrent.locks.ReentrantLock

This is a particle size JDK @since 1.5 added a smaller lock, it can replace the synchronized keyword to implement all of its features, and flexibility ReentrantLock lock is much larger than the synchronized keyword.

Seen from FIG class structure, ReentrantLock achieved Lock interfaces, ReentrantLock just one implementation Lock interface only.

java.util.concurrent.locks.Lock

They are java.util.concurrent package contents inside (commonly known as the JUC, and contract), they are also beginning to join the JDK 1.5.

Why is it called re-entry lock it?

ReentrantLock, we take it apart to see it clear.

Re-Entrant-Lock: means that can be repeatedly re-enter the lock, but only for the current thread;

1
2
3
4
5
6
7
8
9
10
public void m() {
    lock.lock();
    lock.lock();
    try {
      // ... method body
    } finally {
      lock.unlock()
      lock.unlock()
    }
}

如示例代码所示,当前线程可以反复加锁,但也需要释放同样加锁次数的锁,即重入了多少次,就要释放多少次,不然也会导入锁不被释放。

试想一下,如果不设计成可重入锁,那自己如果反复给自己加锁,不是会把自己加死锁了吗?所以,到现在,重入锁的概念大概应该清楚了吧?

重入锁最重要的几个方法

这几个方法都是 Lock 接口中定义的:

1)lock()

获取锁,有以下三种情况:

  • 锁空闲:直接获取锁并返回,同时设置锁持有者数量为:1;
  • 当前线程持有锁:直接获取锁并返回,同时锁持有者数量递增1;
  • 其他线程持有锁:当前线程会休眠等待,直至获取锁为止;

2)lockInterruptibly()

获取锁,逻辑和 lock() 方法一样,但这个方法在获取锁过程中能响应中断。

3)tryLock()

从关键字字面理解,这是在尝试获取锁,获取成功返回:true,获取失败返回:false, 这个方法不会等待,有以下三种情况:

  • 锁空闲:直接获取锁并返回:true,同时设置锁持有者数量为:1;
  • 当前线程持有锁:直接获取锁并返回:true,同时锁持有者数量递增1;
  • 其他线程持有锁:获取锁失败,返回:false;

4)tryLock(long timeout, TimeUnit unit)

逻辑和 tryLock() 差不多,只是这个方法是带时间的。

5)unlock()

释放锁,每次锁持有者数量递减 1,直到 0 为止。所以,现在知道为什么 lock 多少次,就要对应 unlock 多少次了吧。

6)newCondition

返回一个这个锁的 Condition 实例,可以实现 synchronized 关键字类似 wait/ notify 实现多线程通信的功能,不过这个比 wait/ notify 要更灵活,更强大!

重入锁大概的用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class X {

  private final ReentrantLock lock = new ReentrantLock();
  
  // ...

  public void m() {
    lock.lock();  // block until condition holds
    try {
      // ... method body
    } finally {
      lock.unlock()
    }
  }
  
}}

看见没有,加锁和释放锁都在方法里面进行,可以自由控制,比 synchronized 更灵活,更方便。但要注意的是,释放锁操作必须在 finally 里面,不然如果出现异常导致锁不能被正常释放,进而会卡死后续所有访问该锁的线程。

synchronized 是重入锁吗?

那么问题来了,synchronized 是重入锁吗?

你可能会说不是,因为 ReentrantLock 既然是重入锁,根据推理,相反,那 synchronized 肯定就不是重入锁,那你就错了。

答案是:yes,为什么?看下面的例子:

1
2
3
4
5
6
7
public synchronized void operation(){
    add();
}

public synchronized void add(){

}

operation 方法调用了 add 方法,两个方法都是用 synchronized 修饰的,add() 方法可以成功获取当前线程 operation() 方法已经获取到的锁,说明 synchronized 就是可重入锁。

面试常问的Synchronized的几种用法推荐看下这篇文章:Synchronized 有几种用法?

总结

今天,重入锁就大概写到这里了,其实重入锁就是一种颗粒度更小的锁,控制更方便,更强大,栈长只是简单介绍一下重入锁的基本概念及用法,但远不止这么简单,还有很多,一篇也难也详尽,够写好多篇了。

Guess you like

Origin blog.csdn.net/suifeng629/article/details/93907991