AQS(AbstractQueuedSynchronizer)中获取与释放锁分析

说明:本文是我对自己学习知识的一个简单总结,可能存在许多不足,我希望通过此方式来回顾知识,加强理解,也希望大家能指出文中的错误与不足,互相学习,谢谢。

AQS(AbstractQueuedSynchronizer)核心分析

首先看一下类图:
在这里插入图片描述

  • AbstractOwnableSynchronizer是个抽象类,以独占模式设置当前持有的线程。
  • AbstractQueuedSynchronizer从名字来看是抽象的同步队列,这个队列叫做CLH锁队列,CLH锁通常使用的是自旋锁,并且是双向的队列,AQS中还有一种队列叫做条件队列,存储的是"处于等待状态的线程"。CLH队列结构如下:
    在这里插入图片描述

1. Node

接下来看下AQS里面的一个静态内部类,Node,这个类是存储在队列中的基础结构,是用来存储队列中数据的节点,源码如下:

static final class Node {
        /**
         * 节点为共享模式标记
         * */
        static final Node SHARED = new Node();
        /**
         * 节点为独占模式标记
         */
        static final Node EXCLUSIVE = null;
 
        /**
         * 节点为取消状态
         * */
        static final int CANCELLED =  1;
        /**
         * 只要队列前置节点释放锁,为SIGNAL状态的后继节点的线程得以运行。
         */
        static final int SIGNAL    = -1;
        /**
         * 条件队列状态标识
         */
        static final int CONDITION = -2;
        /**
         * 表示下一次共享式同步状态获取将会被无条件地传播下去
         */
        static final int PROPAGATE = -3;
 
        /**
         * 标记当前节点的信号量状态 (1,0,-1,-2,-3)5种状态
         */
        volatile int waitStatus;
 
        /**
         * 前驱节点
         */
        volatile Node prev;
 
        /**
         * 后继节点
         */
        volatile Node next;
 
        /**
         * 节点同步状态的线程
         */
        volatile Thread thread;
 
        /**
         * 条件队列中的下一个节点
         */
        Node nextWaiter;
 
        /**
         * 返回是否是共享节点,这里用来区分独占锁和共享锁
         */
        final boolean isShared() {
            return nextWaiter == SHARED;
        }
 
        /**
         * 返回前驱节点
         */
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }
 
        Node() {   
        }
 
        Node(Thread thread, Node mode) {    
            this.nextWaiter = mode;
            this.thread = thread;
        }
 
        Node(Thread thread, int waitStatus) { // 条件队列构造方法
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
}

2.acquire()方法分析<

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaAQSAbstractQueuedSynchronizer)是实现和同步器的一种重要工具。在AQS,一个节点表示一个线程,依次排列在一个双向队列,同时使用CAS原子操作来保证线程安全。当多个线程对于同一资源竞争时,一个节点会被放置在队列的尾部,其他线程则在其之前等待,直到该资源可以被定。 当一个线程调用lock()方法进行定时,它会首先调用tryAcquire()方法尝试获取。如果当前资源尚未被定,则该线程成功获取,tryAcquire()返回true。如果当前资源已被定,则线程无法获取,tryAcquire()返回false。此时该线程就会被加入到等待队列,同时被加入到前一个节点的后置节点,即成为它的后继。然后该线程会在park()方法处等待,直到前一个节点释放,再重新尝试获取。 在AQS,当一个节点即将释放时,它会调用tryRelease()方法来释放,并唤醒后置节点以重试获取。如果当前节点没有后置节点,则不会发生任何操作。当一个线程在队列头部成功获取和资源时,该线程需要使用release()方法释放和资源,并唤醒等待队列的后置节点。 总之,AQS机制是通过双向等待队列实现的,其节点表示线程,使用CAS原子操作保证线程安全,并在tryAcquire()和tryRelease()方法进行定和释放。该机制保证了多线程环境下资源的正确访问和线程的安全执行。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值