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. 嵊州D1T1 总统先生,一路走好!

    嵊州D1T1 总统先生,一路走好! 在总统先生的所有财产就是 n 杯黑咖啡,咖啡店可以用 m 个空杯子换一杯黑咖啡. 因为总统的特殊身份,心地善良而心生怜悯的咖啡店店长决定先借给总统一杯黑咖啡,只要他 ...

  2. c++学习书籍推荐《超越C++标准库:Boost库导论》下载

    <超越C++标准库Boost库导论>不仅介绍了Boost库的功能.使用方法及注意事项,而且还深入讨论了Boost库的设计理念.解决问题的思想和技巧以及待处理的问题.因此,本书是一本了解Bo ...

  3. MySQL常见操作指令

    1:使用SHOW语句找出在服务器上当前存在什么数据库: mysql> SHOW DATABASES; 2:创建一个数据库MYSQLDATA mysql> CREATE DATABASE M ...

  4. 如果通过脚本来关闭程序-linux

    正常情况下在linux关闭一个程序最好是走正常的关闭流程,不要直接杀死进程,这样程序的稳定性确实会收到影响,但是如果想通过脚本来关闭程序正常情况下比较困难的,我便采取了这种暴力的方法-直接杀死进程. ...

  5. python基础知识三 字典-dict + 菜中菜

    3.7字典:dict+菜中菜 1.简介 ​ 无序,可修改,用于存储数据,大量,比列表快,将数据和数据之间关联 ​ 定义:dict1 = {'cx':10,'liwenhu':80,'zhangyu': ...

  6. storm学习路线指南

    关于对storm的介绍已经有很多了,我这里不做过多的介绍,我介绍一下我自己的学习路线,希望能帮助一些造轮子的同学走一些捷径,毕竟我也是站在前人总结整理的基础上学习了,如果有不足之处,还请大家不要喷我. ...

  7. 第15个算法-实现 Trie (前缀树)(LeetCode)

    解法代码来源 :https://blog.csdn.net/whdAlive/article/details/81084793 算法来源:力扣(LeetCode)链接:https://leetcode ...

  8. 【TensorFlow 1】操作变量

    打印 在tf中直接打印只是输出变量格式,如: #代码 data1 = tf.constant(2,dtype=tf.int32) #浮点数据 data2 = tf.Variable(10,name=' ...

  9. Python秒算24点,行还是不行?

    周末闲来无事,看到隔壁家的老王在和隔壁家的媳妇玩24点,就进屋看了看.发现老王是真不行啊,那不行,这也不行. 就连个24点都玩不过他媳妇,给他媳妇气的,啥都不能满足,这不能,那也不能. 我坐下来和他媳 ...

  10. 跟着大彬读源码 - Redis 7 - 对象编码之简单动态字符串

    Redis 没有直接使用 C 语言传统的字符串表示(以空字符串结尾的字符数组),而是构建了一种名为简单动态字符串(simple dynamic string)的抽象类型,并将 SDS 用作 Redis ...