AQS概念和简单的理解

什么是AQS

Abstract Queued Synchronize(抽象队列同步器)
总起来说就是一些API组件,为了完成像sychnorized的互斥锁,线程阻塞等的一些功能。

synchronized

我们知道synchronized实现互斥锁是通过锁住一个对象完成互斥锁,也就是在对象头中保存线程的地址,如果有其他想锁住对象的时候,会进行等待(通过切换到内核态改变状态)。而重入则是每一次相同的线程进入都把计数器加1,退出减1。

模拟synchronized

  1. 我们通过java代码是无法直接让线程进入阻塞状态,但是JDK中内置了LockSupport进行管理线程的挂起和执行。
  2. 实现互斥锁,通过一个变量指向进入的线程,如果第二次进入的线程不是以保存的线程,则通过LockSupport挂起。
  3. 实现重入,指定一个变量开始的时候为0,当第一个线程进入的时候,变量设置为1,同时把第二部中的变量设置为进入的线程,再一次有线程进入,如果是保存的线程变量加1,否则挂机,并用定义的链表或者集合保存挂起的线程
  4. 实现线程的阻塞(wait()),使用LockSupport挂起线程,并用另一个队列保存。

综上所述模拟synchronized的几步,就是JDK中AQS的实现方法,我们所说的AQS也就是这两个队列

实例

在这里插入图片描述

在这里插入图片描述

如上面两图所示,state表示进入的线程数,而exclusiveOwerThread存储的则是可以进入的线程。

源码

上面知识大致介绍了一下AQS是什么,领略一下JDK的实现吧,代码只涉及主要代码,详细看的朋友自行查看。

lock()

final void lock() {
			// 通过CAS操作给state赋值1,如果成功说明之前没有线程锁定
            if (compareAndSetState(0, 1))
            // exclusiveOwnerThread设置为当前线程
               setExclusiveOwnerThread(Thread.currentThread());
            else
            	// 如果设置失败,已经有线程占用
                acquire(1);
        }

acquire方法:

public final void acquire(int arg) {
			// tryAcquire查看是否是当前线程,如果是state加1,不是则返回false
        if (!tryAcquire(arg) &&
        	// acquireQueued设置挂起线程,详情见下面
        	// addWaiter添加一个节点,放入队列中
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

tryAcquire()中间有一个方法略过:

final boolean nonfairTryAcquire(int acquires) {
			// 获取当前线程
            final Thread current = Thread.currentThread();
            // 获取state的值
            int c = getState();
            // 再一次判断,可能在这个调用过程中,之前的线程已经退出
            if (c == 0) {
                if (compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {
            // 如果是当前线程,则state加1
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

acquireQueued():

final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                // 将状态值设置为-1,成功则返回true
                if (shouldParkAfterFailedAcquire(p, node) &&
                	// 通过Thread.park中断当前线程,循环结束。
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

实现lock的代码如上,unlock,Condation.await和signal,signalAll等代码就不往上写了,都不是很难,大家自己看即可。

总结

简单介绍了AQS的大致实现过程,如果向深入了解互斥锁的实现,点击这里
加油!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值