JDK17 AbstractQueuedSynchronizer 一 同步队列

AQS

抽象队列同步器是JDK提供的用于管理线程间同步状态的类。常见的同步器类ReentrantLock, CountDownLatch, Semaphore等都是AbstractQueuedSynchronizer的子类。

AQS提供三个功能

  1. 提供同步状态。一个是state属性,管理资源的状态。一个是AQS的父抽象类的exclusiveOwnerThread,标记占有资源的线程。
  2. 提供FIFO等待队列。提供线程对象入队、出队、清理无效节点等功能。
  3. 提供条件队列。

状态 state

private volatile int state;
state表示资源的状态,线程根据state判断是否可以争抢资源。以独占模式(同时只能有1个线程获取资源)为例,state=1代表有某个线程掌握资源,exclusiveOwnerThread变量指向该线程。如果某个线程没成功争抢资源,那么进入同步队列,进入休眠,等待唤醒。

同步队列

线程对象是Thread,但是同步队列管理的对象是Node,从下面代码片段可以看出,Node是对Thread的封装以适应队列。

abstract static class Node {
   
	volatile Node prev;       // initially attached via casTail
	volatile Node next;       // visibly nonnull when signallable
	Thread waiter;            // visibly nonnull when enqueued
	volatile int status; 
}

statusstate不同,statusNode的状态,源码中标记三种情况,还有第四种状态0,代表初始化状态,此状态的节点会尝试获取资源,如果未获取变为WAITING,如果有条件变为COND,如果被踢出队列则变为CANCELLED,这是唯一一个小于0的状态。

	static final int WAITING   = 1;          // must be 1
    static final int CANCELLED = 0x80000000; // must be negative
    static final int COND      = 2;          // in a condition wait

同步队列是双向链表,链表的头节点是一个哑节点,用于标记链表。AQS维护head和tail变量。Node可以分为链表Node和游离Node(Node D, Node E)。获取锁,游离节点都可以争抢,链表节点中第一个工作节点(Node A)可以争抢,其余节点不可以争抢。
在这里插入图片描述

争夺资源

acquire(int arg)是AQS提供的争夺资源方法。

public final void acquire(int arg) {
   
        if (!tryAcquire(arg))
            acquire(null, arg, false, false, false, 0L);
    }

首先tryAcquire,AQS本身不定义该方法。这是AQS的实现类定义的获取锁的方法。以ReentrantLock类的NonfairSync非公平同步器为例,它根据state判断是否能获取锁。

protected final boolean tryAcquire(int acquires) {
   
    if (getState() == 0 && compareAndSetState(0, acquires)) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值