ReentrantLock源码分析--jdk1.8
JDK1.8
ArrayList源码分析--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
* 独占锁 --默认使用非公平锁模式
* 可重入
*
* synchronized锁通过监视器Monitor来实现同步,monitorenter加锁,monitorexit解锁。
* synchronized是可重如的非公平锁
* synchronized在jdk1.6进行优化,添加了偏向锁、轻量级锁、重量级锁,关键字之锁的升级(偏向锁->轻量级锁->重量级锁)
* 偏向锁:当线程访问同步块时,会使用 CAS 将线程 ID 更新到锁对象的 Mark Word 中,如果更新成功则获得偏向锁,并且之后每次进入这个对象锁相关的同步块时都不需要再次获取锁了。
* 轻量级锁:如果同步对象为无锁状态时,直接尝试CAS更新Mark Word添加锁,如果成功,获得锁,失败升级为重量级锁
* 重量级锁:是指当锁是轻量级锁时,当自旋的线程自旋了一定的次数后,还没有获取到锁,就会进入阻塞状态,该锁升级为重量级锁,重量级锁会使其他线程阻塞,性能降低。
* 在使用 CAS 时,如果操作失败,CAS 会自旋再次尝试。由于自旋是需要消耗 CPU 资源的,所以如果长期自旋就白白浪费了 CPU。JDK1.6加入了适应性自旋:如果某个锁自旋很少成功获得,那么下一次就会减少自旋。
*/
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的更多相关文章
- JUC AQS ReentrantLock源码分析
警告⚠️:本文耗时很长,先做好心理准备,建议PC端浏览器浏览效果更佳. Java的内置锁一直都是备受争议的,在JDK1.6之前,synchronized这个重量级锁其性能一直都是较为低下,虽然在1.6 ...
- ReentrantLock 源码分析以及 AQS (一)
前言 JDK1.5 之后发布了JUC(java.util.concurrent),用于解决多线程并发问题.AQS 是一个特别重要的同步框架,很多同步类都借助于 AQS 实现了对线程同步状态的管理. A ...
- Java并发编程之ReentrantLock源码分析
ReentrantLock介绍 从JDK1.5之前,我们都是使用synchronized关键字来对代码块加锁,在JDK1.5引入了ReentrantLock锁.synchronized关键字性能比Re ...
- Java并发编程-ReentrantLock源码分析
一.前言 在分析了 AbstractQueuedSynchronier 源码后,接着分析ReentrantLock源码,其实在 AbstractQueuedSynchronizer 的分析中,已经提到 ...
- java多线程---ReentrantLock源码分析
ReentrantLock源码分析 基础知识复习 synchronized和lock的区别 synchronized是非公平锁,无法保证线程按照申请锁的顺序获得锁,而Lock锁提供了可选参数,可以配置 ...
- ArrayList源码分析--jdk1.8
ArrayList概述 1. ArrayList是可以动态扩容和动态删除冗余容量的索引序列,基于数组实现的集合. 2. ArrayList支持随机访问.克隆.序列化,元素有序且可以重复. 3. ...
- JUC之ReentrantLock源码分析
ReentrantLock:实现了Lock接口,是一个可重入锁,并且支持线程公平竞争和非公平竞争两种模式,默认情况下是非公平模式.ReentrantLock算是synchronized的补充和替代方案 ...
- ReentrantLock 源码分析从入门到入土
回答一个问题 在开始本篇文章的内容讲述前,先来回答我一个问题,为什么 JDK 提供一个 synchronized 关键字之后还要提供一个 Lock 锁,这不是多此一举吗?难道 JDK 设计人员都是沙雕 ...
- Java并发系列[5]----ReentrantLock源码分析
在Java5.0之前,协调对共享对象的访问可以使用的机制只有synchronized和volatile.我们知道synchronized关键字实现了内置锁,而volatile关键字保证了多线程的内存可 ...
随机推荐
- WPF 入门笔记之事件
一.事件路由 1. 直接路由事件 起源于一个元素,并且不能传递给其他元素 MouserEnter 和MouserLeave 就是直接事件路由 2. 冒泡路由事件 在包含层次中向上传递,首先由引发的元素 ...
- 算法导论--最小生成树(Kruskal和Prim算法)
转载出处:勿在浮沙筑高台http://blog.csdn.net/luoshixian099/article/details/51908175 关于图的几个概念定义: 连通图:在无向图中,若任意两个顶 ...
- 基于百度EasyDL定制化图像识别平台的海洋鱼类识别方法
[目的]鱼类识别对渔业资源的开发利用有着重要的意义.针对海底环境恶劣.拍摄环境亮度低.场景模糊的实际情况导致海底观测视频品质差,视频中的鱼类识别难的问题以及现有鱼类识别方法存在的鱼类标注数据集过少导致 ...
- C# 与 JS 之间传值在 cshtml页面中
@{ string It = "sss"; ; } @functions{ string Mod = "ajssaioi"; public string Itm ...
- CSingleLock
CSingleLock通常和CCriticalSection配合使用.总结这种用法
- Pascal到c++,求大佬翻译!
请大佬翻译完毕后私信我谢谢! var a,b,c,d,f:array[1..1000]of longint; i,j,k,n,m,o:longint; procedure zx(p,q:longint ...
- SQL SERVER Suspect(质疑/挂起) 状态恢复
数据库服务器,在断电时,偶尔会出现Suspect状态,导致数据库无法使用. 解决办法如下: 数据库名带‘[]’可以避免库名中带‘.’等特殊符号的情况. USE [master]GOALTER DATA ...
- APP爬虫(2)把小姐姐的图片down下来
APP爬虫(1)想学新语言,又没有动力,怎么办? 书接上文.使用appium在帖子列表界面模拟上划动作,捕捉不到列表的规律.上划结束后,列表只能获取到屏幕呈现的部分,而且下标还是从0开始的. 根据酸奶 ...
- 安科 OJ 1190 连接电脑 (并查集)
时间限制:1 s 空间限制:128 M 传送门:https://oj.ahstu.cc/JudgeOnline/problem.php?id=1190 题目描述 机房里有若干台电脑,其中有一些电脑已经 ...
- spring applicationContext.xml文件移到resources目录下
SpringMVC的框架默认目录结构 修改后的目录结构及web.xml 同时在pom里的配置:将resources目录打包到web-inf/classes目录下<resources> ...