JAVA并发编程系列(七)深入理解AQS并发案例
2020-06-05 08:07
113 查看
并发例子:比如三个线程并发通过AQS进行抢锁具体流程如下。
此时AQS
内部数据为:
线程二、线程三加锁失败:
有图可以看出,等待队列中的节点Node
是一个双向链表,这里SIGNAL
是Node
中waitStatus
属性,Node
中还有一个nextWaiter
属性。
具体看下抢占锁代码实现:
java.util.concurrent.locks.ReentrantLock .NonfairSync:
[code]static final class NonfairSync extends Sync { final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } }
这里使用的ReentrantLock非公平锁,线程进来直接利用
CAS尝试抢占锁,如果抢占成功
state值回被改为1,且设置对象独占锁线程为当前线程。如下所示:
[code]protected final boolean compareAndSetState(int expect, int update) { return unsafe.compareAndSwapInt(this, stateOffset, expect, update); } protected final void setExclusiveOwnerThread(Thread thread) { exclusiveOwnerThread = thread; }
线程二抢占锁失败
我们按照真实场景来分析,线程一抢占锁成功后,
state变为1,线程二通过
CAS修改
state变量必然会失败。此时
AQS中
FIFO(First In First Out 先进先出)队列中数据如图所示:
简单说一下非公平锁的实现原理:
AQS内的ReentrantLock默认是基于非公平锁实现的,先用一张图来解释公平锁和非公平锁的区别:
非公平锁执行流程:
这里我们还是用之前的线程模型来举例子,当线程二释放锁的时候,唤醒被挂起的线程三,线程三执行
tryAcquire()方法使用
CAS操作来尝试修改
state值,如果此时又来了一个线程四也来执行加锁操作,同样会执行
tryAcquire()方法。
这种情况就会出现竞争,线程四如果获取锁成功,线程三仍然需要待在等待队列中被挂起。这就是所谓的非公平锁,线程三辛辛苦苦排队等到自己获取锁,却眼巴巴的看到线程四插队获取到了锁。
公平锁执行流程:
公平锁在加锁的时候,会先判断
AQS等待队列中是存在节点,如果存在节点则会直接入队等待,具体代码如下.
公平锁在获取锁是也是首先会执行
acquire()方法,只不过公平锁单独实现了
tryAcquire()方法;、
总结:
非公平锁和公平锁的区别:非公平锁性能高于公平锁性能。非公平锁可以减少
CPU唤醒线程的开销,整体的吞吐效率会高点,
CPU也不必取唤醒所有线程,会减少唤起线程的数量
非公平锁性能虽然优于公平锁,但是会存在导致线程饥饿的情况。在最坏的情况下,可能存在某个线程一直获取不到锁。不过相比性能而言,饥饿问题可以暂时忽略,这可能就是
ReentrantLock默认创建非公平锁的原因之一了。
相关文章推荐
- 深入理解数据库原理系列(2)---并发控制原理(摘自老杨)
- JAVA并发系列十八:深入理解ThreadLocal(二)
- 深入理解数据库原理系列(2)---并发控制原理
- 深入理解javascript原型和闭包系列 深入理解javascript原型和闭包(14)——从【自由变量】到【作用域链】
- 深入理解JavaScript系列(33):设计模式之策略模式
- 深入理解JavaScript系列(6):S.O.L.I.D五大原则之单一职责SRP 转自 博客园 汤姆大叔
- 深入理解JavaScript系列(9):根本没有“JSON对象”这回事!
- 深入理解JavaScript系列(24):JavaScript与DOM(下)
- 深入理解JavaScript系列(17):面向对象编程之一般理论
- 深入理解JavaScript系列(4):立即调用的函数表达式
- 【来龙去脉系列】深入理解DIP、IoC、DI以及IoC容器
- 深入理解Tomcat系列之六 Servlet工作原理
- 深入理解JavaScript系列(13):This? Yes,this!
- 深入理解JavaScript系列(3):全面解析Module模式
- 深入理解JavaScript系列 ----(14):作用域链(Scope Chain)
- 深入理解分布式事务,高并发下分布式事务的解决方案
- 深入理解JavaScript系列(29):设计模式之装饰者模式
- 深入理解JavaScript系列(25):设计模式之单例模式
- 深入理解JavaScript系列(40):设计模式之组合模式
- 深入理解MySQL 5.7 GTID系列(三):GTID的生成时机