什么叫可重入锁

可重入锁,指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的。
synchronized 和 ReentrantLock 都是可重入锁。

可重入锁的意义之一在于防止死锁

废话不多说 直接上源码调试
不知道怎么调试源码的看我之前发的文章
先上下代码哈,注:这篇文章重点讲解锁的重入,有时间再讲AQS个ReentrantLock,先用ReentrantLock为例,他内部维护了一个Sync类 这个Sync又有一个state的变量 这就是可重入的关键
进入代码调试

public class ReentranLockTest  implements Runnable{
    ReentrantLock lock = new ReentrantLock();

    public void get() {
        //第一个断点打再这  state 0->1 由无锁转入有锁
        lock.lock();
        System.out.println(Thread.currentThread().getId());
        set();
        //state 由1->0 至此同一线程的锁变成无锁状态
        lock.unlock();
    }

    public void set() {
        //第二个断点打在这 state 1->2
        lock.lock();
        System.out.println(Thread.currentThread().getId());
        //2->1
        lock.unlock();
    }

    @Override
    public void run() {
        get();
    }

    public static void main(String[] args) {
        ReentranLockTest ss = new ReentranLockTest();
        new Thread(ss).start();
        //new Thread(ss).start();
        //new Thread(ss).start();
    }
}

1.第一个断点 也就是进入get的时候 此时state还是0 无锁的状态
在这里插入图片描述2.进入ReentrantLock lock方法 这个方法是比较现在state的值是不是0 如果是0则利用CAS方式将state致为1
在这里插入图片描述很显然这一步是可以成功的
setExclusiveOwnerThread将当前线程和这把锁进行绑定,防止其他线程占有
结果如下图state变成1了
在这里插入图片描述

3.进入set方法 也就是第二个lock
很显然这里就不是0了 所以走else
在这里插入图片描述这个时候我们就要看acquire方法了
贴一下源码,后面我们会讲tryAcquire,acquire等方法 这些都是AQS里面的方法

public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
    //这里为啥进入了非公平锁的获取是因为在构造ReentranLock时如果是空构造函数,
    //就是非公平锁 后面会将公平锁和非公平锁的底层原理
protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
        ///来到了ReentrantLock的nonfairTryAcquire具体实现方法 先获取state 还是先比较state是不是0 如果不是 就比较当前线程是不是绑定的线程
        //是的话state+1
 final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

按照之前所说 程序走到了state!=0且是当前线程资源
此时state还是1 因为执行还没有到最后的setState
在这里插入图片描述执行setState,如下图 变成了2
在这里插入图片描述

4.断点进入了set方法里的unlock state由2变成1
在这里插入图片描述
5.get的unlock
state由1变成0 变成了无锁状态
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Coffey强

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

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

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

打赏作者

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

抵扣说明:

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

余额充值