可重入锁ReentrantLock的公平锁和非公平锁
参考:https://z.itpub.net/article/detail/C7F9AA816D86898AB8CA9C8E4ACCBD4D
什么是AQS?
AQS即抽象同步队列AbstractQueueSynchronizer, 用于存放所有等着获取锁的排队线程,一个线程对象一个节点。
ReentrantLock 的Sync 内部类有什么作用?
Sync是一个内部抽象类, 有两个继承的子类FairSync 和 NonFairSync,表示公平锁和非公平锁。
new ReentrantLock(Boolean b) 创建的锁是否是公平的, 取决于传入的参数。
继承关系:
FairSync、 NonFairSync -> Sync -> AbstractQueuedSynchronizer (AQS ) -> AbstractOwnableSynchronizer (AOS)
公平锁实现原理:
1、 new ReentrantLock(true)
2、 调用lock 方法时,判断state = 0, 等于0表示第一次加锁, =1 表示锁重入了一次。
3、 state = 0 时:
hasQueuedPredecessors 方法判断是否有比当前线程更早的节点, 有的话直接return false获取锁失败。
如果是排队最早的节点, compareAndSetState 设置state=1 , setExclusiveOwnerThread 设置占用锁的线程为当前线程。
4、state !=0, 表示当前锁已经被人持有。 如果是正好是当前线程持有,重入一次; 如果不是返回false获取锁失败。
以下是实现源码:
1 /** 2 * Sync object for fair locks 3 */ 4 static final class FairSync extends Sync { 5 private static final long serialVersionUID = -3000897897090466540L; 6 /** 7 * Fair version of tryAcquire. Don't grant access unless 8 * recursive call or no waiters or is first. 9 */ 10 @ReservedStackAccess 11 protected final boolean tryAcquire(int acquires) { 12 final Thread current = Thread.currentThread(); 13 int c = getState(); 14 if (c == 0) { 15 if (!hasQueuedPredecessors() && 16 compareAndSetState(0, acquires)) { 17 setExclusiveOwnerThread(current); 18 return true; 19 } 20 } 21 else if (current == getExclusiveOwnerThread()) { 22 int nextc = c + acquires; 23 if (nextc < 0) 24 throw new Error("Maximum lock count exceeded"); 25 setState(nextc); 26 return true; 27 } 28 return false; 29 } 30 }
非公平锁的实现原理:
lock 方法获取锁时, 与公平锁的逻辑一样, 只是少了 hasQueuedPredecessors()方法的判断, 也就是不判断当前节点是否是头结点(排队最久的节点)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了