可重入锁和不可重入锁的区别

这篇博客探讨了可重入锁与不可重入锁的概念,通过Java代码示例展示了它们的工作原理。不可重入锁在同一个线程尝试重入上锁代码段时会导致死锁,而可重入锁则允许线程重复进入已锁定的代码块,防止死锁并确保线程安全性。Java的ReentrantLock和synchronized关键字作为可重入锁的例子被提及。
摘要由CSDN通过智能技术生成

不可重入锁示例(同一个线程不可以重入上锁后的代码段)

如下是一个不可重入锁的逻辑过程,会发现执行main方法控制台会打印执行doJob方法前,然后就会一直线程阻塞,不会打印执行doJob方法过程中,原因在于第一次上锁后,由于没有释放锁,因此执行第一次lock后isLocked = true,这个时候调用doJob()内部又一次调用了lock()由于上个线程将isLocked = true,导致再次进入的时候就进入死循环。导致线程无法执行System.out.println("执行doJob方法过程中");这行代码,因此控制台只能打印执行doJob方法前。这种现象就造成了不可重入锁

public class Count{
    MyLock lock = new MyLock();

    public static void main(String[] args) throws InterruptedException {
        new Count().doSomeThing(); // 示例的main方法
    }
    public void doSomeThing() throws InterruptedException {
        lock.lock(); // 第一次上锁
        System.out.println("执行doJob方法前");
        doJob(); // 方法内会再次上锁
        lock.unlock(); // 释放第一次上的锁
    }
    public void doJob() throws InterruptedException {
        lock.lock();
        System.out.println("执行doJob方法过程中");
        lock.unlock();
    }
}

/**
 * 自定义锁
 */
class MyLock{
    private boolean isLocked = false;
    public synchronized void lock() throws InterruptedException{
        while(isLocked){
            wait();
        }
        isLocked = true; // 线程第一次进入后就会将器设置为true,第二次进入是就会由于where true进入死循环
    }
    public synchronized void unlock(){
        isLocked = false;   // 将这个值设置为false目的是释放锁
        notify();           // 接触阻塞
    }
}

可重入锁示例(同一个线程可以重入上锁的代码段,不同的线程则需要进行阻塞)

java的可重入锁有:ReentrantLock(显式的可重入锁)synchronized(隐式的可重入锁)

可重入锁诞生的目的就是防止上面不可重入锁的那种情况,导致同一个线程不可重入上锁代码段。

目的就是让同一个线程可以重新进入上锁代码段。

设计可重入锁的示例代码

public class MyReentrantLock {
    boolean isLocked = false;   // 默认没有上锁
    Thread lockedBy = null; // 记录阻塞线程
    int lockedCount = 0;    // 上锁次数计数

    /**
     * 上锁逻辑
     */
    public synchronized void lock() throws InterruptedException {
        Thread thread = Thread.currentThread();
        // 上锁了 并且 如果是同一个线程则放行,否则其它线程需要进入where循环进行等待
        while (isLocked && lockedBy != thread) { 
            wait();
        }
        isLocked = true; // 第一次进入就进行上锁
        lockedCount++; // 上锁次数计数
        lockedBy = thread; // 当前阻塞的线程
    }

    /**
     * 释放锁逻辑
     */
    public synchronized void unlock() {
        if (Thread.currentThread() == this.lockedBy) {
            lockedCount--; // 将上锁次数减一
            if (lockedCount == 0) {// 当计数为0,说明所有线程都释放了锁
                isLocked = false; // 真正的将释放了所有锁
                notify();
            }
        }
    }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诗水人间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值