网站建设属于技术服务吗,用wordpress做博客,厦门网站制作建设,网站功能插件—— AQS#xff08;AbstractQueuedSynchronizer#xff09;
概念
抽象队列同步器#xff1b;volatile cas 机制实现的锁模板#xff0c;保证了代码的同步性和可见性#xff0c;而 AQS 封装了线程阻塞等待挂起#xff0c;解锁唤醒其他线程的逻辑。AQS 子类只需要根据状…—— AQSAbstractQueuedSynchronizer
概念
抽象队列同步器volatile cas 机制实现的锁模板保证了代码的同步性和可见性而 AQS 封装了线程阻塞等待挂起解锁唤醒其他线程的逻辑。AQS 子类只需要根据状态变量判断是否可获取锁是否释放锁使用 LockSupport 挂起、唤醒线程即可定义是用来实现锁或者其他同步器组件的公共基础部分的抽象实现是重量级基础框架及整个 JUC 体系的基石主要用于解决锁分配的问题官网为实现阻塞锁和相关的同步器提供一个框架依赖于先进先出的一个等待依靠单个原子 int 值来表示状态通过占用和释放方法改变状态值整体就是一个抽象的 FIFO 队列来完成资源获取线程的排队工作并通过一个 volatile 的 int 类型变量state表示持有锁的状态CLHCraig、Landin、Hagersten队列是一个单向链表AQS 中的队列是 CLH 变体的虚拟双向队列 FIFO 为什么 AQS 是 JUC 中最重要的基石
ReentrantLock 、CountDownLatch、ReentrantReadWriteLock、Semaphore 等都与 AQS 有关锁 和 同步器的关系 锁是面向锁的使用者定义了程序员和锁交互的使用层 API隐藏了实现细节同步器是面向锁的实现DougLee 提出统一规范并简化了锁的实现将其抽象出来屏蔽了同步状态管理、同步队列的管理和维护、阻塞线程排队和通知、唤醒机制等是一切锁和同步组件实现的公共基础部分
作用
多个线程抢占共享资源只有一个线程抢占成功其他线程必然涉及一种排队等候机制如果共享资源被占用就需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是 CLH 队列的变体实现将暂时获取不到锁的线程加入到队列中这个队列就是 AQS 同步队列的抽象表现。它将要请求共享资源的线程及自身的等待状态封装成队列的节点对象Node通过 CAS、自旋以及 LockSupport.park() 的方式维护 state 变量的状态使并发达到同步的效果
ReentrantLock 公平锁 和 非公平锁的 lock() 方法唯一的区别在获取同步状态时多了一个限制条件 hasQueuedPredecessors()这是公平锁加锁时判断等待队列中是否存在有效节点的方法
源码分析
整个 ReentrantLock 的加锁过程可以分为三个阶段 尝试加锁tryAcquire() 当出现 锁已经被其他线程获取 / 锁没有被其他线程获取但当前线程需要排队 / cas 失败 这三种情况时会导致获取锁失败锁为自由状态并不能说明可以立刻执行 cas 获取锁因为可能在当前线程获取锁之前已经有其他线程在排队了必须 遵循先来后到的原则获取锁。还要调用 hasQueuedPredecessors()方法查看自己是否需要排队 加锁失败线程进入队列acquireQueued() 线程入队列后进入阻塞状态addWaiter() 具体细节查看源码
—— ReentrantReadWriteLock可重入读写锁
概念
读写锁定义一个资源能够被多个读线程访问或者被一个写线程访问但是不能同时存在读写线程读写互斥、读读共享只有在读多写少的情景之下读写锁才具有较高的性能表现缺点 写锁饥饿问题出现大面积读锁只有几个写锁存在写锁长时间抢占不到锁的情况锁降级将写锁降级为读锁锁的严苛程度变强叫升级反之叫降级 如果同一个线程持有了写锁在没有释放写锁的情况下它还可以继续获得读锁。这就是写锁的降级降级成了读锁遵循 获取写锁——》获取读锁——》释放写锁——》释放读锁 的次序可以实现锁降级反之读锁升级到写锁是不可能的如果有线程在读未释放读锁前则该线程是无法获取写锁的是悲观锁的策略锁降级源码总结 —— StampedLock邮戳锁
概念
StampedLock 是 JDK1.8 中新增的一个读写锁也是对 JDK1.5 中的读写锁 ReentrantReadWriteLock的优化stamp戳记long类型代表了锁的状态。当stamp返回 0 时表示线程获取锁失败。并且当释放锁或者转换锁的时候都要传入最初获取的stamp值使用乐观锁策略可以解决 ReentrantReadWriteLock 锁饥饿的问题使用公平锁策略一定程度上也可以缓解但是需要以牺牲系统吞吐量为代价StampedLock 对短的只读代码段使用乐观模式通常可以减少争用并提高吞吐量
缺点
StampedLock 不支持重入没有 Re 开头StampedLock 的悲观读锁和写锁都不支持条件变量Condition使用 StampedLock 一定不要中断操作即不要调用 interrupt() 方法
正常情况下ReentrantLock 和 ReentrantReadWriteLock 业务场景还是较多