Java提高——JUC锁01-框架

Java锁机制详解
本文详细介绍了Java中的锁机制,包括同步锁和JUC包中的多种锁。解释了Lock接口、ReadWriteLock接口、ReentrantLock、ReentrantReadWriteLock等概念,并讨论了AQS类在实现这些锁中的关键作用。

根据锁得添加到Java时间,Java中的锁可以分为“同步锁”和“JUC包中的锁

同步锁

即通过synchronized关键字来进行同步,实现竞争资源互斥访问的锁。

同步锁的原理:每个对象有且仅有一个同步锁,不同线程能够共同访问该同步锁,但是,同一时点,该同步锁只能被一个线程获取到。这样获取到同步锁的线程就能够进行CPU调度,在CPU上执行;而没有获取到同步锁的线程必须进行等待,直到获取到同步锁之后才能够继续运行。这就是多线程通过同步锁进行同步的原理。

JUC包中的锁

JUC包中的锁包括:Lock接口、ReadWriteLock接口、LockSupport阻塞原语、condition条件、AbstractOwnableSynchronizer / AbstractQueuedSynchronizer / AbstractQueuedLongSynchronizer三个抽象类,ReentrantLock独占锁,ReentrantReadWriteLock读写锁。由于CountDownLatch, CyclicBarrier和Semaphore也是通过AQS来是实现的,因此我们将其归纳到锁的框架中进行介绍。

1、Lock接口

JUC中的Lock接口支持那些语义不同(重入、公平等)的锁的规则。所谓语义不同是指锁有“公平机制的锁”、“非公平机制的锁”、“可重入的锁”等等。“公平机制”是指不同线程获取锁的机制是公平的。而“非公平机制”是指不同线程获取锁的机制是非公平的,“可重入的锁”是指同一个锁能够被同一个线程多次获取。

2、ReadWriteLock
ReadWriteLock接口以和Lock类似的方式定义了一些读取者可以共享而写入者独占的锁。JUC包只有一个类实现了该接口,即ReentrantReadWriteLock,因为它适用于大部分的标准用法上下文。但程序员可以自己创建、使用于非标准要求的实现。
3、AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizer

AbstractQueuedSynchronizer是被称为AQS的类,他是一个非常有用的超类,可以用来定义锁以及依赖于排队阻塞线程的其他其他同步器;ReentrantLock,ReentrantReadWriteLock,CountDownLatch,CyclicBarrier和Semaphore等这些类都是基于AQS实现的。AbstractQueuedLongSynchronizer类提供了相同的功能但是扩展了对同步状态的64位支持。两者都扩展了类AbstractOwnablleSynchronizer(一个帮助记录当前保持独占同步的线程的简单类)

4、LockSupport

LockSupport提供“创建锁”和“其他同步类的基本线程阻塞原语”

LockSupport的功能和“Thread中的Thread.suspend()和Thread.resume()”有点类似。LockSupport中的park()和unpark()的作用分别是阻塞线程和解除阻塞线程。但是park()和unpark()不会遇到Thread.suspend()和Thread.resume()可能引发的死锁问题。

5、Condition

Condition需要和Lock联合使用,它的作用是代替Object的监视器方法,可以通过await(),signal()唤醒线程。

Condition接口描述了可能会与锁有关联的条件变量。这些变量在用法上与Object.wait()访问的隐式监视器类似,但提供了更强大的功能。需要特别指出的是,单个Lock可能与多个Condition对象关联。为了避免兼容性问题,Condition方法的名称和对应的Object中的不同。

6、ReentrantLock

ReentrantLock是独占锁。即同一个时间点只能被同一个线程获取到的锁。ReentrantLock包括“公平的ReentrantLock”和“非公平的ReentrantLock”。“公平的ReentrantLock”是指不同线程获取锁的机制是公平的,“非公平的ReentrantLock”是指不同线程获取锁的机制是非公平的。ReentrantLock是可重入的锁

ReentrantLock的UML图:

1)ReentrantLock实现了Lock接口。

2)ReentrantLock中有一个成员变量sync,sync对象是Sync类型的,Sync是一个抽象类,它继承了AQS

3)ReentrantLock中有“公平锁类FairSync”和“非公平锁类NonFairSync”,他们都是Sync类的子类。ReentrantReadWriteLock中sync对象是FairSync和NonFairSync中的一种,这意味着ReentrantLock是“公平锁”或“非公平锁”中的一种,ReentrantLock默认是非公平锁。     

7、ReentrantReadWriteLock

ReentrantReadWriteLock是读写锁接口ReadWriteLock的实现类,它包括子类ReadLock和WriteLock。ReentrantLock是共享锁,而ReadLock是独占锁。ReentrantReadWriteLock的UML图:


ReentrantReadWriteLock实现了ReadWriteLock接口。

ReentrantReadWriteLock包含了sysn对象,读锁readLock和写锁writeLock。并且读锁readLock和写锁writeLock都实现了Lock接口。

和“ReentrantLock”一样,sync是Sync类型的,而且Sync也是一个继承AQS的抽象类。Sync包括“公平锁FairSync”和“非公平锁NonFairSync”。

8、CountDownLatch

CountDownLatch是一个同步辅助类在完成一组其他线程中执行的操作前,它允许一个或多个线程一直等待

CountDownLatch的UML图:


CountDownLatch包含了sync对象,sync是Sync类型。CountDownLatch的sync是实例类,继承于AQS。

9、CyclicBarrier

CyclicBarrier是一个同步辅助类允许一些线程相互等待,直到到达某个公共屏障点,因为该barrier在释放等待线程后可以会重用,所以称为循环的barrier。

CyclicBarrier的UML图:


CyclicBarrier包含了“ReentrantLock对象lock”和“Condition对象trip”,它通过独占锁实现的。

CyclicBarrier和CountDownLatch的区别:

1)CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则允许N个线程相互等待。

2)CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此他被称为是循环的barrier

10、Semaphore

Semaphore是一个计数信号量,它的本质是一个共享锁

信号量维护了一个信号量许可集。线程可以通过调用acquire()来获取信号量的许可;当信号量中有可用的许可时,线程能够获取该许可;否则线程必须等待直到有可用的许可为止。线程可以通过release()来释放它所持有的信号量许可。

Semaphore的UML图:

和“ReentrantLock”一样,Semaphore包含了sync对象,sync是Sync类型,而且Sync也是一个继承于AQS的抽象类。Sync也包括“公平信号量”FairSync和“非公平信号量”NonFairSync



转载于:https://www.cnblogs.com/huangzhe1515023110/p/9276047.html

### Java JUC AQS 并发编程 抽象队列同步器 使用教程 源码解析 #### 什么是AQS? `AbstractQueuedSynchronizer`(简称AQS),作为Java并发包中的核心组件之一,提供了用于实现和其他同步器的基础框架。它不仅简化了和同步工具的创建过程,还提高了这些工具的工作效率[^2]。 #### 类图结构与工作原理 AQS的设计围绕着一个FIFO(先进先出)等待队列展开,该队列由多个节点组成,每个节点代表了一个正在等待获取资源的线程。每当有新的竞争者未能立即获得所需资源时,就会被构造成一个新的节点并加入到这个队列之中;而当现有持有者释放其持有的资源之后,则会从队头开始依次唤醒后续等待者去尝试占有资源[^5]。 #### 同步模式分类 为了适应不同场景下的需求,AQS支持两种主要类型的同步方式——独占式以及共享式: - **独占式**:一次只允许单个线程访问临界区,在这种情况下其他任何试图进入同一区域内的请求都将被迫挂起直到前序操作完成为止; - **共享式**:允许多个读取者同时存在而不互相干扰,只要不存在写入动作发生即可保持一致性和安全性[^3]。 #### 自定义同步器的关键接口 对于想要利用AQS来构建特定行为逻辑的新类型而言,开发者通常需要重载以下几个抽象方法以适配具体的应用环境: - `tryAcquire(int arg)` 和 `tryRelease(int arg)` - `tryAcquireShared(int arg)` 及 `tryReleaseShared(int arg)` - `isHeldExclusively()` 上述函数分别对应于独占/共享模式下对资源的操作控制流程,通过合理地覆盖它们可以轻松打造出满足业务特性要求的各种高级别同步原语[^1]。 ```java public class CustomSync extends AbstractQueuedSynchronizer { protected boolean tryAcquire(int acquires) { // 实现具体的独占式获取逻辑 return super.tryAcquire(acquires); } protected boolean tryRelease(int releases) { // 实现具体的独占式释放逻辑 return super.tryRelease(releases); } } ``` #### 队列管理机制详解 在实际运行过程中,AQS内部维护了一条双向链表形式的数据结构用来存储各个待处理的任务单元。每当新成员到来之时便会调用`enqueue()`方法将其追加至末端位置上形成完整的链条关系网状链接,并且借助CAS指令保证整个插入过程的安全可靠性质不受外界因素影响破坏[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值