默认构造方法初始化同步器为非公平同步器

    /**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
}

lock()方法调用的是sync的lock()方法

    public void lock() {
sync.lock();
} final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}

如果将state从0改为1成功,那么将属性exclusiveOwnerThread改为当前线程,代表获得锁成功

    protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
} protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}

修改失败走acquire,参数arg为1

public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}

三步走

1.tryAcquire调用的是nonfairTryAcquire

protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}

//aquire为1
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
  //这个逻辑什么时候会走?其他线程第一次抢锁失败,然后恰好获得锁的线程释放了锁?
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
  //获得锁的线程重入会走这个逻辑
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}

2.又一次抢锁失败,且不是当前线程重入,tryAcquire返回false,走下一步逻辑acquireQueued(addWaiter(Node.EXCLUSIVE), arg))

2.1 addWaiter(Node.EXCLUSIVE)  (将新节点插入尾节点之后,如果尾节点为空,初始化一个新节点,没有线程,既是头也是尾,返回新节点有thread没有addwaiter)

private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
//如果有尾节点,将当前节点插入尾节点之后(可能其他线程也在做此事,失败了没关系下一步会处理)
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
} Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
} private Node enq(final Node node) {
for (;;) {
Node t = tail;
//尾节点为空,初始化一个新节点,头和尾都指向他
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
//将node节点放入尾节点之后,一次次直到成功
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
} Node() { // Used to establish initial head or SHARED marker
}

2.2 acquireQueued

final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
       //如果前一个结点是头节点,尝试获得锁,获得锁后,将自己设为头节点,前头节点置空
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
       //将当前节点的前一个结点的waitStatus改为-1(循环直到成功),挂起当前节点lockSupport.park
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}

ReentrantLock源码阅读的更多相关文章

  1. Java多线程——ReentrantLock源码阅读

    上一章<AQS源码阅读>讲了AQS框架,这次讲讲它的应用类(注意不是子类实现,待会细讲). ReentrantLock,顾名思义重入锁,但什么是重入,这个锁到底是怎样的,我们来看看类的注解 ...

  2. Java多线程——ReentrantReadWriteLock源码阅读

    之前讲了<AQS源码阅读>和<ReentrantLock源码阅读>,本次将延续阅读下ReentrantReadWriteLock,建议没看过之前两篇文章的,先大概了解下,有些内 ...

  3. 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分

    这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int ...

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

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

  5. Rpc框架dubbo-client(v2.6.3) 源码阅读(二)

    接上一篇 dubbo-server 之后,再来看一下 dubbo-client 是如何工作的. dubbo提供者服务示例, 其结构是这样的!dubbo://192.168.11.6:20880/com ...

  6. ThreadPoolExecutor 源码阅读

    目录 ThreadPoolExecutor 源码阅读 Executor 框架 Executor ExecutorService AbstractExecutorService 构造器 状态 Worke ...

  7. 【详解】ThreadPoolExecutor源码阅读(二)

    系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) AQS在W ...

  8. 【详解】ThreadPoolExecutor源码阅读(一)

    系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) 工作原理简 ...

  9. 死磕 java同步系列之ReentrantLock源码解析(二)——条件锁

    问题 (1)条件锁是什么? (2)条件锁适用于什么场景? (3)条件锁的await()是在其它线程signal()的时候唤醒的吗? 简介 条件锁,是指在获取锁之后发现当前业务场景自己无法处理,而需要等 ...

  10. CyclicBarrier源码阅读

    一种允许多个线程全部等待彼此都到达某个屏障的同步机制 使用 多个线程并发执行同一个CyclicBarrier实例的await方法时,每个线程执行这个方法后,都会被暂停,只有当最后一个线程执行完awai ...

随机推荐

  1. Docker容器 获取宿主机CPU信息等或重启网卡命令操作介绍

    一.作用场景及知识点 1. 使用场景(SSH方式除外): A. 运行在Docker容器里面的程序,怎么采集宿主机的CPU.内存.磁盘等信息: B. 容器内更改宿主机的网卡信息,怎么操作宿主机执行命令: ...

  2. 网络时间同步系统(NTP授时服务器)在电信网络的技术性应用研究

    网络时间同步系统(NTP授时服务器)在电信网络的技术性应用研究 网络时间同步系统(NTP授时服务器)在电信网络的技术性应用研究 岳峰 15901092122 --------------------- ...

  3. Ant Design 抽屉(tabel)

    效果图如下,因部分涉及到人员隐私,所以打码了,就是一些图片文字信息. 有不足的地方可以麻烦提出来的,一起学习的. <template> <a-drawer v-model:visib ...

  4. HCIA-ICT实战基础12-网络设备安全特性

    HCIA-ICT实战基础-网络设备安全特性 目录 常见设备安全加固策略 网络设备安全加固部署示例 本机防攻击配置 1 常见设备安全加固策略 1.1 为什么需要网络设备安全 网络安全是一个系统工程, 网 ...

  5. Notepad++轻量级java环境

    2020-07-11 summary: Notepad++搭建轻量级java环境 notepad++搭建轻量级Java 原因:不想用eclipse 一.本机环境 Windows10 64位 已安装No ...

  6. 用Python中的hashlib实现md5和sha加密

    文章目录 一.用 pandas 读取 Excel 数据 二.加密库 hashlib 三. pandas中的 map() 方法 四.数据加密工具 本文分享知识: pandas读取Excel数据 read ...

  7. Mysql 字段加密

    1.PASSWORD() 2.ENCODE(,)   DECODE(,) 3.MD5()4.SHA5() 5.AES_ENCRYPT AES_DECRYPT 加密 select   aes_encry ...

  8. 通达OA设计表单的小总结

    16px下: 2010-09-09  80px  一般 100px  占5个字符 2010年09月09日 112px 一般120px 对应计算控件30px 占7个字符 2010-09-09时分秒 14 ...

  9. java 操作excel

    需要引入的包 import org.apache.poi.hssf.usermodel.*; import org.apache.poi.ss.usermodel.HorizontalAlignmen ...

  10. CSS设置边距

    1.内边距 所有的 ​HTML ​元素基本都是以矩形为基础. 每个 HTML 元素周围的矩形空间由三个重要的属性来控制: ​padding(内边距)​ ​margin(外边距)​ ​border(边框 ...