AQS介绍

abstractQueueSync 作为juc 并发包下的核心,reentrantlock,smphere,CountDownLatch都是内部类Sync 实现了abstractQueueSync CyclicBarrier 也用到了它

reentrantlock 用的是排他锁

smphere,countdownlatch 用的是共享锁

CyclicBarrier用的是 reentrantlock +condition

所有实现类

Queue ? 队列?

找遍了 AbstractQueuedSynchronizer 里面没有发现真正的队列,只有一个内部类Node,这个Node里面有 前后指针 指向下一个node ,这其实是一个双向链表 。

同时有 Node head 标记为队列第一位置

java 复制代码
AbstractQueuedSynchronizer{
    private transient volatile Node head;

    private transient volatile Node tail;

    private volatile int state;

    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;      // written by owner, atomic bit ops by others
  }
 } 

当我们 tryAcquire 如果失败的时候 会调用

AbstractQueuedSynchronizer # acquire(Node node, int arg, boolean shared,

boolean interruptible, boolean timed, long time)

去生成一个 Node

java 复制代码
    public final void acquire(int arg) {
        if (!tryAcquire(arg))
            acquire(null, arg, false, false, false, 0L);
    }
java 复制代码
    final int acquire(Node node, int arg, boolean shared,
                      boolean interruptible, boolean timed, long time) {
        Thread current = Thread.currentThread();
        byte spins = 0, postSpins = 0;   // retries upon unpark of first thread
        boolean interrupted = false, first = false;
        Node pred = null;   
  }

独占锁

规则:

  1. state ==0 才可以抢锁
  2. 抢到后ExclusiveOwnerThread 设置成当前线程
  3. 没抢到放到【队列里面】

reentrantlock 用的是独占锁

抢到锁的把 ExclusiveOwnerThread 设置成当前线程

并且设置 state = 1

公平锁

java 复制代码
static final class FairSync extends Sync {
        /**
         * Acquires only if thread is first waiter or empty
         */
        protected final boolean tryAcquire(int acquires) {
            if (getState() == 0 && !hasQueuedPredecessors() &&
                compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }
}

可以看到公平锁需要 在state = 0 的情况下 还要看下下一个是不是当前线程 ,

调用hasQueuedPredecessors() 查看下一个线程是不是自己

java 复制代码
 public final boolean hasQueuedPredecessors() {
        Thread first = null; Node h, s;
        if ((h = head) != null && ((s = h.next) == null ||
                                   (first = s.waiter) == null ||
                                   s.prev == null))
            first = getFirstQueuedThread(); // retry via getFirstQueuedThread
        return first != null && first != Thread.currentThread();
    }

非公平锁

java 复制代码
        /**
         * Acquire for non-reentrant cases after initialTryLock prescreen
         */
        protected final boolean tryAcquire(int acquires) {
            if (getState() == 0 && compareAndSetState(0, acquires)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

非公平锁只要判断state ==0 就可以抢锁了

ReentrantLock 的多重继承

ReentrantLock 设计很巧妙,用的是组合方式

java 复制代码
public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;
    /** Synchronizer providing all implementation mechanics */
    private final Sync sync;
			/** Sync 才继承 AbstractQueuedSynchronizer   **/
        abstract static class Sync extends AbstractQueuedSynchronizer {
        		private static final long serialVersionUID = -5179523762034025860L;
        }
		/** 内部类 NonfairSync  又继承了 Sync 并且实现了 tryAcquire **/
	 static final class NonfairSync extends Sync {
	 			protected final boolean tryAcquire(int acquires) {}
	 }
		
		/** 内部类 FairSync 又继承了 Sync 并且实现了 tryAcquire **/
	 static final class FairSync extends Sync {
	 protected final boolean tryAcquire(int acquires) {}
	 }	

    }

NonfairSync 和 FairSync 只 实现了 tryAcquire 哈 ,因为释放逻辑不需要区分

tryRelease 是在 Sync

java 复制代码
 abstract static class Sync extends AbstractQueuedSynchronizer {
        protected final boolean tryRelease(int releases) {
            int c = getState() - releases;
            if (getExclusiveOwnerThread() != Thread.currentThread())
                throw new IllegalMonitorStateException();
            boolean free = (c == 0);
            if (free)
                setExclusiveOwnerThread(null);
            setState(c);
            return free;
        }
  }

ReentrantLock 使用 组合 + 内部类继承 AQS 的结构,

主要解决 Java 以下问题:

  1. Java 单继承限制
    外部类不占用继承名额,扩展更灵活。
  2. 策略切换不灵活(公平 / 非公平)
    用组合实现策略模式,运行时切换公平 / 非公平,避免类爆炸。
  3. API 暴露不安全、封装破坏
    内部类隐藏 AQS 底层方法,对外只暴露安全 API。
  4. 代码复用(模板方法)
    公共逻辑放父 Sync,差异逻辑放 Fair/Nonfair,减少重复代码。

共享锁

相关推荐
个 人 练 习 生1 分钟前
C++ string 类模拟实现:从底层理解字符串(上)
开发语言·c++·经验分享·学习·程序人生
2601_9669496510 分钟前
多市场量化策略的数据接口应该如何设计:从数据层架构到策略接入
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
坤坤子吖13 分钟前
C++智能指针:RAII、shared_ptr与内存泄漏
开发语言·c++·笔记·学习
奋斗的阿狸_198623 分钟前
ESP32-S3 + ES7210 四通道麦克风录音上传方案
c语言·开发语言·fpga开发
夜之眷属37 分钟前
Core dump 崩溃排查:JVM 宕机后,那份 core 文件怎么用 gdb 还原现场
java·运维·服务器·jvm
weixin1997010801638 分钟前
《1688图片空间API踩坑:img.upload 与 album.* 的防盗链与CDN缓存问题》(附Python源码)
开发语言·python·缓存
波加曼大王40 分钟前
# vLLM不要迷信PagedAttention神话,聊聊线上藏着的内部碎片陷阱
java·架构
SL_staff44 分钟前
目标健康度自检清单:开发者视角下的目标-计划-任务链路断点诊断
java·开源·github
for_ever_love__1 小时前
MySQL 高频面试题 30 问:索引、事务、锁、日志、主从与分库分表(MySQL 8.0 版)
java·数据库·spring boot·mysql·spring cloud·面试·总结
神仙别闹1 小时前
基于C++实现的贪吃蛇游戏平台
java·c++·游戏