JUC并发编程(十二)--可重入锁

一、什么是可重入锁

同一个线程可以多次上锁代码段。

二、不可重入锁

指的就是同一个线程不能多次上锁代码段。
代码实例:

package com.zhan.juc.lock;

/**
 * 可重入锁demo
 * @Author Zhanzhan
 * @Date 2021/2/6 13:59
 */
public class ReentrantLockDemo {

    static MyLock myLock = new MyLock();

    public static void main(String[] args) throws InterruptedException {
        testMyLock1();
    }

    /**
     * 测试不可重入锁,即在单个线程内,多次上锁,看是否可以,还是会阻塞线程
     * @throws InterruptedException
     */
    public static void testMyLock1() throws InterruptedException {
        myLock.lock(); // 第一次上锁
        System.out.println("执行testMyLock2()前---");
        testMyLock2(); // 这个方法内再次上锁
        myLock.unlock();
    }

    public static void testMyLock2() throws InterruptedException {
        myLock.lock();
        System.out.println("执行testMyLock2()中---");
        myLock.unlock();
    }

    /**
     * 自定义一个不可重入锁
     */
    static class MyLock{
        private boolean isLocked = false;

        /**
         * 加锁
         * @throws InterruptedException
         */
        public synchronized void lock() throws InterruptedException {
            while (isLocked){
                wait();
            }
            isLocked = true; // 线程第一次进入后就会将标识设置为true,第二次进入时就会因为while(true)进入死循环
        }

        /**
         * 解锁
         */
        public synchronized void unlock(){
            isLocked = false; // 将这个值设置为false,目的就是释放锁
            notify();
        }
    }
}

看结果:
在这里插入图片描述
我们发现,第一次上锁后,如果再次上锁,就会一直阻塞,即不可重入。

三、可重入锁实现

上代码:

package com.zhan.juc.lock;

/**
 * 可重入锁demo
 * @Author Zhanzhan
 * @Date 2021/2/6 13:59
 */
public class ReentrantLockDemo {

    static MyLock myLock = new MyLock(); // 不可重入锁对象

    static MyReentrantLock myReentrantLock = new MyReentrantLock(); // 可重入锁对象

    public static void main(String[] args) throws InterruptedException {
        testMyReentrantLock();
    }

    /**
     * 测试不可重入锁,即在单个线程内,多次上锁,看是否可以,还是会阻塞线程
     * @throws InterruptedException
     */
    public static void testMyLock1() throws InterruptedException {
        myLock.lock(); // 第一次上锁
        System.out.println("执行testMyLock2()前---");
        testMyLock2(); // 这个方法内再次上锁
        myLock.unlock();
    }

    public static void testMyLock2() throws InterruptedException {
        myLock.lock();
        System.out.println("执行testMyLock2()中---");
        myLock.unlock();
    }

    /**
     * 测试可重入锁,即在单个线程内,可以多次上锁
     * @throws InterruptedException
     */
    public static void testMyReentrantLock() throws InterruptedException {
        myReentrantLock.lock(); // 上锁
        System.out.println("testMyReentrantLock2()前---");
        testMyReentrantLock2(); // 这个方法内再次上锁
        myReentrantLock.unlock();
    }

    public static void testMyReentrantLock2() throws InterruptedException {
        myReentrantLock.lock();
        System.out.println("执行testMyReentrantLock2()中---");
        myReentrantLock.unlock();
    }

    /**
     * 自定义一个可重入锁
     */
    static class MyReentrantLock{
        private boolean isLocked = false;
        private Thread lockedBy = null; // 用来记录要上锁的线程
        private int lockedCount = 0; // 上锁次数计数

        /**
         * 上锁
         * @throws InterruptedException
         */
        public synchronized void lock() throws InterruptedException {
            // 获取当前线程
            Thread thread = Thread.currentThread();
            // 如果上锁了,并且不是同一个线程,或者不是目标线程,就会进入循环等待
            while (isLocked && lockedBy != thread){
                wait(); // 阻塞非目标线程
            }
            isLocked = true; // 进行上锁
            lockedCount++; // 上锁次数+1
            lockedBy = thread; // 当前要上锁的目标线程
        }

        /**
         * 解锁
         */
        public synchronized void unlock(){
            // 如果是目标线程,就开始释放锁
            if (Thread.currentThread() == lockedBy){
                lockedCount--; // 将上锁次数 -1
                // 当上锁计数为 0,则说明目标线程已经释放了所有的锁
                if (lockedCount == 0){
                    isLocked = false; // 将上锁的标识设置为 false,真正的释放了目标线程所有重入的锁
                    notify();
                }
            }
        }
    }

    /**
     * 自定义一个不可重入锁
     */
    static class MyLock{
        private boolean isLocked = false;

        /**
         * 加锁
         * @throws InterruptedException
         */
        public synchronized void lock() throws InterruptedException {
            while (isLocked){
                wait();
            }
            isLocked = true; // 线程第一次进入后就会将标识设置为true,第二次进入时就会因为while(true)进入死循环
        }

        /**
         * 解锁
         */
        public synchronized void unlock(){
            isLocked = false; // 将这个值设置为false,目的就是释放锁
            notify();
        }
    }
}

测试结果:
在这里插入图片描述
符合预期!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值