ReentrantLock对AbstractQueuedSynchronizer的使用

1.ReentrantLock的骨架

由ReentrantLock的目录结构可知,ReentrantLock有三个内部类,Sync,FairSync,NonfairSync。

其中FairSync,NonfairSync继承了Sync,Sync继承了AbstractQueuedSynchronizer。

FairSync和NonfairSync也就是我们常说的公平锁和非公平锁。
公平锁和非公平锁的概念:https://blog.csdn.net/qq_35688140/article/details/100546216
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
故由上面可知:ReentrantLock实际上就是对AbstractQueuedSynchronizer的封装加使用。

在java中,AbstractQueuedSynchronizer是给Java工程师提供的一个控制并发的模板类。

2.核心AQS

reentrantLock中AQS代码如下:reentrantLock所有代码都是为了调用AQS而设计的。包括加锁和释放锁都是对AQS的方法的调用实现的。

 abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        // 非公平锁和公平锁实现lock的方式不同,所以这里设置成抽象方法
        abstract void lock();

        // 非公平锁获取锁的方式,公平锁改写了该方法,加入了对队列头部的线程的判断
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();//获取锁的状态,compareAndSetState回对state更新,获取锁时state=1,释放锁后state=0
            if (c == 0) {
                if (compareAndSetState(0, acquires)) { //核心方法,下面讲解
                    setExclusiveOwnerThread(current);//设置当前线程位独占锁
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {//c!=0,且锁已经被独占
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);//更新state值
                return true;
            }
            return false;
        }

        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;//获取最新的状态,
            if (Thread.currentThread() != getExclusiveOwnerThread())//锁被当前线程独占
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {//如果最新的状态为0,
                free = true;
                setExclusiveOwnerThread(null);//释放独占锁
            }
            setState(c);//重置state为0,放置在此方法运行期间,state被修改
            return free;
        }

		//判断锁的持有者是否是当前线程独有
        protected final boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        final ConditionObject newCondition() {
            return new ConditionObject();
        }

        // 获取锁的持有者
        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }

        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }

		//获取所的状态
        final boolean isLocked() {
            return getState() != 0;
        }

        /**
         * Reconstitutes the instance from a stream (that is, deserializes it).
         */
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }

由上面的代码可以看出最核心的方法就是不断地compareAndSetState(0, acquires)这个操作,不断的用一个原子方法修改state的值。

3.compareAndSwapInt

compareAndSetState(0, acquires)两个参数,期望值,和修改后的值。通过判断state是否是我们期望的值来保证数据没有被修改。如果没有被修改则执行操作,被修改了返回false。

经过代码跟踪发现它一直调用的是unsafe的compareAndSwapInt方法。这是unsafe这个java后门,可以操作java底层内存,修改对象,设置某个对象的偏移量等等。因此这个方法不安全,随意很容易引发一系列内存问题。java也是不推荐使用此方法的,但是很多高性能框架,入netty(可以直接向直接缓冲区中写入数据就是通过该方法。以此绕过了堆缓冲区)
在这里插入图片描述

4.队列

相比于非公平锁,公平锁多了的判断hasQueuedPredecessors()

protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                if (!hasQueuedPredecessors() && // 判断是否在线程队列的头部
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

跟踪代码:发现AbstractQueuedSynchronizer一直在维护一个队列,公平锁会判断执行的该线程是否在队列的头部。
在这里插入图片描述

5.condition

reentrantLock维持了不同的condition,不同condition上的线程是互不影响
在这里插入图片描述
跟进源码:我们发现每个condition维持一个队列,因为condition是一个局部变量,所以不同线程之间互不影响。如果await和signal就进行一个入队出队的操作即可。
在这里插入图片描述
await
在这里插入图片描述
signal
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值