目录

  • 一、重入锁的理解
  • 二、方式一:使用synchronized演示例重入锁示例
  • 三、方式二:使用ReentrantLock演示例重入锁示例
  • 四、使用ReentrantLock演示例重入锁示例(加锁和释放次数不一样导致的死锁)


一、重入锁的理解

  • 某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。
  • 可重入锁,也叫做递归锁。指的是同一线程外层函数获得锁之后,内层递归函数仍然能够获得该锁的代码。
  • 在同一个线程,在外层方法获取锁的时候,进入内层方法时会自动获取锁。
  • synchronized和ReentrantLock都是可重入的。
  • 可重入锁最大的作用就是避免死锁。
  • 重入降低了编程复杂性。

二、方式一:使用synchronized演示例重入锁示例

1、代码

package com.xz.thread.t5;

/**
 * @description: 第一种方式:使用synchronized演示例重入锁
 * @author: xz
 */
public class Demo3 {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (this){
                    System.out.println("第1次获取锁,这个锁是:" + this);
                    int index=1;
                    while(true){
                        synchronized (this){
                            System.out.println("第" + (++index) + "次获取锁,这个锁是:" + this);
                        }
                        if (index == 10) {
                            break;
                        }
                    }
                }
            }
        }).start();
    }
}

2、输出结果

Java 使用重入锁 java重入锁有什么用_重入锁


3、结论

  • 由第2步截图可知,没有发生死锁,可以多次获取相同的锁。

三、方式二:使用ReentrantLock演示例重入锁示例

1、使用ReentrantLock的注意点

  • ReentrantLock 和 synchronized 不一样,需要手动释放锁,所以使用 ReentrantLock的时候一定要手动释放锁,并且加锁次数和释放次数要一样。

2、代码

package com.xz.thread.t5;

import java.util.concurrent.locks.ReentrantLock;

/**
 * @description: 第一种方式:使用ReentrantLock演示例重入锁
 * @author: xz
 */
public class Demo4 {
    public static void main(String[] args) {
        ReentrantLock reentrantLock = new ReentrantLock();

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    reentrantLock.lock();
                    System.out.println("第1次获取锁,这个锁是:" + reentrantLock);

                    int index=1;
                    while (true) {
                        try {
                            reentrantLock.lock();
                            System.out.println("第" + (++index) + "次获取锁,这个锁是:" + reentrantLock);
                            if (index == 10) {
                                break;
                            }
                        }finally {
                            reentrantLock.unlock();
                        }
                    }
                } finally {
                    reentrantLock.unlock();
                }
            }
        }).start();
    }
}

3、输出结果

Java 使用重入锁 java重入锁有什么用_System_02


4、结论

  • 由第3步截图可知,没有发生死锁,可以多次获取相同的锁。

四、使用ReentrantLock演示例重入锁示例(加锁和释放次数不一样导致的死锁)

1、代码

package com.xz.thread.t5;

import java.util.Random;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @description: 使用ReentrantLock演示例重入锁(加锁和释放次数不一样导致的死锁)
 * @author: xz
 */
public class Demo5 {
    public static void main(String[] args) {
        ReentrantLock reentrantLock = new ReentrantLock();
        //第一个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    reentrantLock.lock();
                    System.out.println("第1次获取锁,这个锁是:" + reentrantLock);

                    int index = 1;
                    while (true) {
                        try {
                            reentrantLock.lock();
                            System.out.println("第" + (++index) + "次获取锁,这个锁是:" + reentrantLock);
                            try {
                                Thread.sleep(new Random().nextInt(200));
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            if (index == 10) {
                                break;
                            }
                        } finally {
                            //lock.unlock();// 这里故意注释,实现加锁次数和释放次数不一样
                        }
                    }
                } finally {
                    reentrantLock.unlock();
                }
            }
        }).start();

        //第二个线程
        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    reentrantLock.lock();
                    for (int i = 0; i < 20; i++) {
                        System.out.println("threadName:" + Thread.currentThread().getName());
                        try {
                            Thread.sleep(new Random().nextInt(200));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                } finally {
                    reentrantLock.unlock();
                }
            }
        }).start();
    }
}

2、输出结果

Java 使用重入锁 java重入锁有什么用_Java 使用重入锁_03

3、结论

  • 由第3步截图可知,由于第一个线程加锁次数和释放次数不一样,导致第二个线程始终无法获取到锁,一直在等待。