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

王炸

同一个线程,可以上两次锁就是可重入锁。

只能上一次锁,若二次上锁则造成死锁为不可重入锁。

不可重入锁

package lao.ben.juc.lock;

/**
 * 自定义不可重入锁
 */
public class NoAgainLock {


    private boolean isLocked = false;

    //线程第一次进入后就会将器设置为true,第二次进入是就会由于while true进入死循环
    public synchronized void lock() throws InterruptedException {
        while (isLocked) {
            wait();
        }
        isLocked = true;
    }


    //释放锁,接触阻塞
    public synchronized void unlock() {
        isLocked = false;
        notify();
    }
}



package lao.ben.juc.lock;

//不可重入锁
public class NoTest {


    NoAgainLock lock = new NoAgainLock();


    public static void main(String[] args) throws InterruptedException {
        new NoTest().doTry();
    }


    public void doTry() throws InterruptedException {
        //第一次上锁,外部锁
        lock.lock();
        System.out.println("准备执行doReduce()");
        //方法内会再次上锁,内部锁
        //进入就出不来了
        doReduce();
        System.out.println("我猜:永远不会走到这一步");
        //释放第一次上的锁
        lock.unlock();
    }


    public void doReduce() throws InterruptedException {
        //锁上加锁,还都是同一把锁
        lock.lock();
        System.out.println("执行doJob方法过程中");
        lock.unlock();
    }


}

可重入锁


package lao.ben.juc.lock;



//可重入锁
//可重入锁增加了计数器以及记录当前拿到锁的线程
public class MyReentrantLock {

    //默认没有上锁
    boolean isLocked = false;
    //记录当前拿到锁的线程
    Thread lockedBy = null;
    //上锁次数计数
    int lockedCount = 0;


    /**
     * 上锁逻辑
     *
     * 线程1第一次进入,计数器+1
     * 线程2第一次进入,发现没有锁,开始排队。
     * 线程1第二次进入,计数器+1
     *
     */
    public synchronized void lock() throws InterruptedException {
        Thread thread = Thread.currentThread();
        // 上锁了 并且 如果是同一个线程则放行,否则其它线程需要进入while循环进行等待
        while (isLocked && lockedBy != thread) {
            wait();
        }
        //线程1第一次进入就进行上锁
        isLocked = true;
        //上锁次数计数递增
        lockedCount++;
        //当前拿到锁的线程为线程1
        lockedBy = thread;
    }


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

可重入锁的实现原理

与不可重入锁相比,可重入锁本身不那么激进。

为锁关联一个持有者和计数器,以线程为粒度获取锁。

1、张三使用锁A,锁A记录使用者为张三,计数器+1,张三再次使用锁A,计数器再次+1。

2、张三退出同步代码块,计数器逐步递减,直至为0,锁释放。

3、计数器次数代表这个线程现在重入了几次。即只有当计数器为0时,代表所有线程都释放了锁。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值