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的更多相关文章

  1. JUC AQS ReentrantLock源码分析

    警告⚠️:本文耗时很长,先做好心理准备,建议PC端浏览器浏览效果更佳. Java的内置锁一直都是备受争议的,在JDK1.6之前,synchronized这个重量级锁其性能一直都是较为低下,虽然在1.6 ...

  2. ReentrantLock 源码分析以及 AQS (一)

    前言 JDK1.5 之后发布了JUC(java.util.concurrent),用于解决多线程并发问题.AQS 是一个特别重要的同步框架,很多同步类都借助于 AQS 实现了对线程同步状态的管理. A ...

  3. Java并发编程之ReentrantLock源码分析

    ReentrantLock介绍 从JDK1.5之前,我们都是使用synchronized关键字来对代码块加锁,在JDK1.5引入了ReentrantLock锁.synchronized关键字性能比Re ...

  4. Java并发编程-ReentrantLock源码分析

    一.前言 在分析了 AbstractQueuedSynchronier 源码后,接着分析ReentrantLock源码,其实在 AbstractQueuedSynchronizer 的分析中,已经提到 ...

  5. java多线程---ReentrantLock源码分析

    ReentrantLock源码分析 基础知识复习 synchronized和lock的区别 synchronized是非公平锁,无法保证线程按照申请锁的顺序获得锁,而Lock锁提供了可选参数,可以配置 ...

  6. ArrayList源码分析--jdk1.8

    ArrayList概述   1. ArrayList是可以动态扩容和动态删除冗余容量的索引序列,基于数组实现的集合.  2. ArrayList支持随机访问.克隆.序列化,元素有序且可以重复.  3. ...

  7. JUC之ReentrantLock源码分析

    ReentrantLock:实现了Lock接口,是一个可重入锁,并且支持线程公平竞争和非公平竞争两种模式,默认情况下是非公平模式.ReentrantLock算是synchronized的补充和替代方案 ...

  8. ReentrantLock 源码分析从入门到入土

    回答一个问题 在开始本篇文章的内容讲述前,先来回答我一个问题,为什么 JDK 提供一个 synchronized 关键字之后还要提供一个 Lock 锁,这不是多此一举吗?难道 JDK 设计人员都是沙雕 ...

  9. Java并发系列[5]----ReentrantLock源码分析

    在Java5.0之前,协调对共享对象的访问可以使用的机制只有synchronized和volatile.我们知道synchronized关键字实现了内置锁,而volatile关键字保证了多线程的内存可 ...

随机推荐

  1. Mysql CPU使用率长期100%的解决思路备忘

    最近一台服务器的CPU使用率长期保持在100%的状态,查看进程发现是Mysql服务导致的.于是搜索各方资料,终于成功解决问题.备忘以及分享一下,希望可以帮助各位新手朋友. (服务器运行环境是Windo ...

  2. mysql+mybatis存储超大json

    1. 场景描述 因前端界面需存储元素较多,切割后再组装存储的话比较麻烦,就采用大对象直接存储到mysql字段中,根据mysql的介绍可以存放65535个字节,算了算差不多,后来存的时候发现: 一是基本 ...

  3. CDQZ集训DAY6 日记

    又炸了. 早上起来其他竞赛生也走了,食堂做饭做的挺潦草,但为什么四川烧麦的馅是米啊??!! 起来看题总觉得都似曾相识.第一题打完40分暴力后想拿莫队搞到70分,但发现能想到的莫队维护都是nsqrt(n ...

  4. [笨方法学Python]ImportError"No module named bin.app"【笔记】

    运行nosetests时,出现:ImportError"No module named bin.app" 解决方法: 1.检查路径是否是bin/app.py 2.检查是否创建bin ...

  5. vue2.0 富文本组件(基于wangeditor)

    1. 本组件基于 wangeditor http://www.wangeditor.com/ 如有侵权 请告知, 2. 效果图 3. 依赖安装 package.json 中 devDependenci ...

  6. C语言入门4-运算符和表达式

    一.     分类 C语言一共有34种运算符,10种运算类型,本节我们要掌握的有( 7 种) 算术运算符(+.-.*./.%). 关系运算符(>.>=.==.!=.<.<=). ...

  7. 【git】15分钟学会使用Git和远程代码库

    Git是个了不起但却复杂的源代码管理系统.它能支持复杂的任务,却因此经常被认为太过复杂而不适用于简单的日常工作.让我们诚实一记吧:Git是复杂的,我们不要装作它不是.但我仍然会试图教会你用(我的)基本 ...

  8. 剖析std::function接口与实现

    目录 前言 一.std::function的原理与接口 1.1 std::function是函数包装器 1.2 C++注重运行时效率 1.3 用函数指针实现多态 1.4 std::function的接 ...

  9. vue+ elementUI 打包发布到服务器后,element-icons.woff文件404

    vue项目打包部署到服务器,静态资源文件404 js文件404问题        原因:打包的项目静态资源的路径需要设置为绝对路径.如果是相对路径会出错 解决办法:修改config/index.js文 ...

  10. iOS 注释

    1) 参数的注释: UIButton *btnSend;/**< 发送按钮 */ 效果: 2) 方法的注释: type1(无参数): /** table 相关设置 */ -(void)confi ...