Java中ReentrantLock特征之可重入和可打断

163 阅读1分钟

 ``` 本文已参与「新人创作礼」活动,一起开启掘金创作之路。


## 可重入

        可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁\
        如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡住

### synchronized可重入举例

static final Object obj = new Object(); public static void method1() { synchronized( obj ) { // 同步块 A method2(); } } public static void method2() { synchronized( obj ) { // 同步块 B } }


![](<> "点击并拖拽以移动")

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/00866b8189dc4796b9106d9cffbceb55~tplv-k3u1fbpfcp-zoom-1.image)![](<> "点击并拖拽以移动")​编辑

###  ReentrantLock可重入举例

static ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) { method1(); } public static void method1() { lock.lock(); try { log.debug("execute method1"); method2(); } finally { lock.unlock(); } } public static void method2() { lock.lock(); try { log.debug("execute method2"); method3(); } finally { lock.unlock(); } } public static void method3() { lock.lock(); try { log.debug("execute method3"); } finally { lock.unlock(); } }


![](<> "点击并拖拽以移动")

运行结果,输出

> 17:59:11.862 [main] c.TestReentrant - execute method1\
> 17:59:11.865 [main] c.TestReentrant - execute method2\
> 17:59:11.865 [main] c.TestReentrant - execute method3

## 可打断

        synchronized锁不可打断,ReentrantLock的lockInterruptibly()方法可以在等锁的过程中被interrupt打断,结束等待

> 示例
>
> ```
> ReentrantLock lock = new ReentrantLock();
> Thread t1 = new Thread(() -> {
>
>     log.debug("启动...");
>     try {
>         lock.lockInterruptibly();
>     } catch (InterruptedException e) {
>         e.printStackTrace();
>         log.debug("等锁的过程中被打断");
>         return;
>     }
>     try {
>         log.debug("获得了锁");
>     } finally {
>         lock.unlock();
>     }
> }, "t1");
> lock.lock();
> log.debug("获得了锁");
> t1.start();
> try {
>     sleep(1);
>     t1.interrupt();
>     log.debug("执行打断");
> } finally {
>     lock.unlock();
> }
> ```

> 输出
>
> 18:02:40.520 [main] c.TestInterrupt - 获得了锁\
> 18:02:40.524 [t1] c.TestInterrupt - 启动...\
> 18:02:41.530 [main] c.TestInterrupt - 执行打断\
> java.lang.InterruptedException\
>         at\
> java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchr\
> onizer.java:898)\
>         at\
> java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchron\
> izer.java:1222)\
>         at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)\
>         at cn.itcast.n4.reentrant.TestInterrupt.lambda$main$0(TestInterrupt.java:17)\
>         at java.lang.Thread.run(Thread.java:748)\
> 18:02:41.532 [t1] c.TestInterrupt - 等锁的过程中被打断

         通过ReentrantLock创建的条件变量(简单理解为休息室),可以调用signal方法,唤醒全部等待的线程。

​