JUC代码浅析[2]——基于AQS的锁ReentrantLock
ReentrantLock是使用比较普遍的一个可重入锁,它是互斥的,一个锁只能被一个线程占有。它的方法基本都是委托给继承AQS的Sync实现的。其中Sync有两种实现,公平和非公平。Sync使用state(通过AQS暴露的getState和setState方法)保存线程的获取次数。总的策略为state次数为0时可以获得锁。大于0时,如果当前线程已经拥有该锁则可再次获得,否则进入AQS的调度逻辑(<JUC代码浅析——同步器AQS>中介绍)。下面为非公平ReentrantLock的NonfairSync实现,
final void lock() {
if (compareAndSetState(0,
1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
如果state次数为0的话,获得成功并设置当前线程为锁的拥有者。
否则进入AQS调度,acquire(1)方法使用tryAcquire尝试获得,这里重载的tryAcquire调用的是nonfairTryAcquire方法
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//如果当前重进入数为0,有机会取得锁
if (c == 0) {
//获得成功并设置当前线程为锁的拥有者
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//如果当前线程已经拥有该锁则可再次获得
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum
lock count exceeded");
setState(nextc);
return true;
}
//都不满足,则进入AQS队列等待调度
return false;
}
公平ReentrantLock的FairSync实现
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//如果当前重进入数为0,有机会取得锁
if (c == 0) {
//如果当前线程是第一个等待者,获得成功并设置当前线程为锁的拥有者
if (isFirst(current) &&
compareAndSetState(0,
acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//如果当前线程已经拥有该锁则可再次获得
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum
lock count exceeded");
setState(nextc);
return true;
}
//都不满足,则进入AQS队列等待调度
return false;
}
fairSync和NonfairSync的tryRelease方法是同一个,比较简单,就是改变一下state次数,如果需要的话把拥有者线程置为null
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() !=
getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
公平和非公平的区别就在于,尝试进入的时候需要判断当前线程是否是队列的第一个,是第一个才能进入。这样AQS在调度的时候就会阻塞掉很多线程,性能差别就比较大。ReentrantLock只支持互斥模式,没有共享模式
分享到:
相关推荐
Java 多线程与并发(10_26)-JUC锁_ 锁核心类AQS详解
狂神说JUC代码
7、深入理解 AQS 独占锁之 Reentrantlock 源码分析 (1).pdf 8、读写锁ReentrantReadWriteLock&StampLock详解.pdf 9、并发容器 (Map、List、Set) 实战及其原理.pdf 10、阻塞队列BlockingQueue 实战及其原理分析.pdf
从JUC中的AQS引入,讲解Java volatile与AQS锁内存可见性
juc 的aqs介绍。
本资源描述了Java并发常见的问题AQS的加锁解锁的过程
Java 并发编程中的 JUC(java.util.concurrent)库以及其核心组件 AQS(AbstractQueuedSynchronizer)在构建高性能、可伸缩性的多线程应用方面具有重要的地位。 AQS 是 JUC 中的核心组件,它提供了一个框架,让...
Java 多线程与并发(11_26)-JUC锁_ ReentrantLock详解
AQS源码分析一、锁的介绍1.1 乐观锁/悲观锁1.2 共享锁/独占锁1.3 公平锁/非公平锁1.4 小结二、AQS框架结构介绍2.1 类图2.2 AQS数据结构三、源码详解3.1 acquire源码详解3.2 release源码详解四、从ReentranLock看公平...
详细阐述了ReentrantLock通过AQS获取锁到释放锁的过程,附有关键方法的源码及注释
JUC代码收集,java高并发多线程学习
个人学习的时候对JUC做的笔记,包括所有代码,学习视频是尚硅谷周阳老师的JUC,需要有一定的基础才能看懂,这是个人笔记,不一定适用于所有人,谢谢!
JUC是什么 线程 进程 / 线程 线程状态 wait / sleep 并发 / 并行 Lock 使用Lock锁 可重入锁 公平锁 / 非公平锁 Synchronized / Lock 线程通讯 wait()、notify()和notifyAll() 虚假唤醒 Condition 定制化通信 多线程...
JUC线程锁框架深度解析,包含整套视频和源码以及开发文档。
JUC代码演示 Java多线程并发 源于B站https://www.bilibili.com/video/BV1Kw411Z7dF/?p=32&spm_id_from=333.1007.top_right_bar_window_history.content.click课程自我项目记录。 适合有一定基础的朋友。
ReentrantLock Lock 加锁过程源码分析图,AQS 源码分析
8. Lock接口 (ReentrantLock 可重入锁) 特性 ReentantLock 继承接口 Lock 并实现了接口中定义的方法, 它是一种可重入锁, 除了能完成 synchronized 所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁...
juc学习代码。。。。
juc并发编程脑图以及相关示例代码
尚硅谷_JUC线程高级_volatile 关键字与内存可见性 ·2. 尚硅谷_JUC线程高级_原子变量与 CAS 算法 ·3. 尚硅谷_JUC线程高级_模拟 CAS 算法 ·4. 尚硅谷_JUC线程高级_同步容器类ConcurrentHashMap ·5. 尚硅谷_JUC...