ReentrantLock源码分析--jdk1.8
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReentrantLock源码分析--jdk1.8相关的知识,希望对你有一定的参考价值。
JDK1.8ArrayList源码分析--jdk1.8
LinkedList源码分析--jdk1.8
HashMap源码分析--jdk1.8
AQS源码分析--jdk1.8
ReentrantLock源码分析--jdk1.8
ReentrantLock概述
??1. ReentrantLock是独占锁。
??2. ReentrantLock分为公平模式和非公平模式。
??3. ReentrantLock锁可重入(重新插入)
ReentrantLock源码分析
/**
* @since 1.5
* @author Doug Lea
* 独占锁 --默认使用非公平锁模式
* 可重入
*/
public class ReentrantLock implements Lock, java.io.Serializable
private static final long serialVersionUID = 7373984872572414699L;
private final Sync sync;
/**
* Sync内部类,继承AQS,实现独占锁模式,作为基础内部类
*/
abstract static class Sync extends AbstractQueuedSynchronizer
private static final long serialVersionUID = -5179523762034025860L;
/**
* 加锁
*/
abstract void lock();
/**
* 判断 reentranLock 状态 是否被锁住(state ?= 0)
* <p>如果没被锁住尝试 原子性上锁 失败返回false</>
* <p>如果被锁住 判断是否是当前线程持有锁(重入锁的实现) 如果是 state + 1
* (信号量 记录该线程持有锁的次数。 该线程每次释放所 信号量 -1。 信号量为零 代表 锁被真正释放)</>
* <p>else 返回false</p>
*/
final boolean nonfairTryAcquire(int acquires)
final Thread current = Thread.currentThread(); //获取到当前的线程
int c = getState(); //获取锁的状态
if (c == 0) //目前没有人在占有锁 如果锁已被经释放 再次尝试获取锁
if (compareAndSetState(0, acquires)) //直接尝试把当前只设置成1,如果成功,把owner设置自己,并且退出
setExclusiveOwnerThread(current);
return true;
else if (current == getExclusiveOwnerThread()) // 如果当前线程为锁的拥有者
int nextc = c + acquires; //这里就是重入锁的概念,如果还是自己,则进行加1操作,因为释放和获取一定要是对等的
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc); // 累加 state 的值 此段代码 实现了重入锁
return true;
return false; //当前锁被其他线程占用,退出。
/**
* 释放锁,默认releases传1
*/
protected final boolean tryRelease(int releases)
int c = getState() - releases; //获取当前的锁的状态并且减1,因为要释放锁
if (Thread.currentThread() != getExclusiveOwnerThread()) //如果当前自己不是锁的持有者,只有自己才能释放锁
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) //释放成功
free = true;
setExclusiveOwnerThread(null);
setState(c); //重新设置成状态
return free;
/**
* 如果当前线程独占着锁,返回true
*/
protected final boolean isHeldExclusively()
// While we must in general read state before owner,
// we don‘t need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
/**
* 条件队列
*/
final ConditionObject newCondition()
return new ConditionObject();
/**
* 返回锁的拥有者的线程
* 当前状态为0返回null,说明在等待中
* 当前状态不为0返回当前线程
*/
final Thread getOwner()
return getState() == 0 ? null : getExclusiveOwnerThread();
/**
* 当前线程占着锁返回 state,否则返回0
*/
final int getHoldCount()
return isHeldExclusively() ? getState() : 0;
/**
* state状态不为0标识上锁,为0表示在等待,不上锁
*/
final boolean isLocked()
return getState() != 0;
/**
* 反序列化
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException
s.defaultReadObject();
setState(0); // reset to unlocked state
/**
* 构造方法,默认选择非公平锁
*/
public ReentrantLock()
sync = new NonfairSync();
/**
* 构造方法,true公平锁,false非公平锁
*/
public ReentrantLock(boolean fair)
sync = fair ? new FairSync() : new NonfairSync();
ReentrantLock继承和实现分析
?? ReentrantLock implements Lock
?? Sync extends AbstractQueuedSynchronizer
?? 1.ReentrantLock实现Lock接口,Lock接口定义了加锁、条件队列、解锁、加锁(中断异常)
?? 2.Sync继承AQS抽象类,实现了独占锁,作为基础内部类ReentrantLock源码分析
1. FairSync公平锁--内部类
/**
* 公平锁
*/
static final class FairSync extends Sync
private static final long serialVersionUID = -3000897897090466540L;
final void lock()
acquire(1);
/**
* Fair version of tryAcquire. Don‘t grant access unless
* recursive call or no waiters or is first.
*/
protected final boolean tryAcquire(int acquires)
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0)
if (!hasQueuedPredecessors() &&
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;
return false;
2. NonfairSync非公平锁--内部类
/**
* 非公平锁的同步对象
*/
static final class NonfairSync extends Sync
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
* 非公平锁,每次先去获取对象,所以不排队,不公平
*/
final void lock()
// 通过原子操作 改变上锁状态
if (compareAndSetState(0, 1)) // 变更成功,说明获取锁成功
setExclusiveOwnerThread(Thread.currentThread()); // 设置持有者为当前线程
else //变更失败
acquire(1); //尝试以独占模式获取锁,如果失败加入node节点到队列中
protected final boolean tryAcquire(int acquires)
return nonfairTryAcquire(acquires);
/**
* 是否有等待线程
*/
public final boolean hasQueuedThreads()
return sync.hasQueuedThreads();
/**
* 是否有等待线程
*/
public final boolean hasQueuedThreads()
return head != tail;
ReentrantLock总结
1)ReentrantLock是可重入的公平/非公平模式的独占锁。
2)ReentrantLock公平锁往往没有非公平锁的效率高,但是,并不是任何场景都是以TPS作为唯一指标,公平锁
能够减少“饥饿”发生的概率,等待越久的请求越能够得到优先满足。
以上是关于ReentrantLock源码分析--jdk1.8的主要内容,如果未能解决你的问题,请参考以下文章
ConcurrentHashMap 源码详细分析(JDK1.8)
jdk1.8 J.U.C并发源码阅读------ReentrantLock源码解析