本文紧接上文的AQS源码,如果对于ReentrantLock没有基础可以先阅读我的上一篇文章学习ReentrantLock的源码

ReentrantLock锁重入原理

重入加锁其实就是将AQS的state进行加一操作

然后释放锁资源将AQS的state进行减一操作

当state为0时才会彻底的释放锁资源

ReentrantLock可打断原理

在ReentrantLock中可打断就是在等待锁的过程中可以被interrupt打断(需要调用lockInterruptibly),lock方法设置了打断标记,但是只有在线程获得锁的时候才能知道自己有没有在阻塞的过程中有没有被打断。

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; // 返回打断标记
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())// 我们这边会检查打断,如果打断的话返Thread.interrupted()
interrupted = true; // 这里将打断标记置为true后,继续进入循环。直到获得到锁返回标记
}
} finally {
if (failed)
cancelAcquire(node);
}
}

首先我们需要调用加锁的lockInterruptibly()方法

public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}

可打断主要原因在如下代码解释。用异常代替了返回标记,让线程可以直接再park的过程中直接结束

private void doAcquireInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException(); // 再被打断的时候不会将其标记置为true,而是直接抛出一个异常,打断当前的等待。
}
} finally {
if (failed)
cancelAcquire(node);
}
}

ReentrantLock条件变量原理

Condition是一个接口,实际上是ReentrantLock的ConditionObject类作为其实现类。

首先我们创建一个condition就会调用其构造方法。其实就是产生一个新的conditionObject

final ConditionObject newCondition() {
return new ConditionObject();
}

await()源码

接下来,简单剖析一个源码

  • 首先我们得知道,ConditionObject中维护着一个等待的双向链表,其实和阻塞链表是很相似的,不同在于不需要前驱进行唤醒。然后在ConditionObject中维护头和尾的引用就是firstWaiter和lastWaiter成员变量。
public final void await() throws InterruptedException {
if (Thread.interrupted()) // 如果被打断,抛异常
throw new InterruptedException();
Node node = addConditionWaiter(); // 1.向AQS中添加一个等待链表的node
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) { // 是否在阻塞链表中
LockSupport.park(this); // 不是的话直接进行阻塞起来
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)// 被打断了就得把它放阻塞链表
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE) // 多线程的遗留状态处理
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
  1. 添加等待node
private Node addConditionWaiter() {
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters(); // 这个和阻塞队列相似不过是全部遍历,清除不在等待队列上的node
t = lastWaiter;
}
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null) // 添加到waitting尾部
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
return node;
}

signal源码

signal唤醒源码,简单介绍就是直接将等待的firstWaiter指向的等待链表的第一个进行解除阻塞,然后将其放入阻塞链表中。不过多赘述。

public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}

ReentrantLock可重入、可打断、Condition原理剖析的更多相关文章

  1. ReentrantLock——可重入锁的实现原理

    一. 概述 本文首先介绍Lock接口.ReentrantLock的类层次结构以及锁功能模板类AbstractQueuedSynchronizer的简单原理,然后通过分析ReentrantLock的lo ...

  2. ReenTrantLock可重入锁(和synchronized的区别)总结

    ReenTrantLock可重入锁(和synchronized的区别)总结 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也 ...

  3. ReenTrantLock可重入锁和synchronized的区别

    ReenTrantLock可重入锁和synchronized的区别 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也是可重入 ...

  4. JUC 一 ReentrantLock 可重入锁

    java.util.concurrent.locks ReentrantLock即可重入锁,实现了Lock和Serializable接口 ReentrantLock和synchronized都是可重入 ...

  5. ReentrantLock可重入锁的理解和源码简单分析

    import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; /** * @author ...

  6. 【java并发编程】ReentrantLock 可重入读写锁

    目录 一.ReentrantLock可重入锁 二.ReentrantReadWriteLock读写锁 三.读锁之间不互斥 欢迎关注我的博客,更多精品知识合集 一.ReentrantLock可重入锁 可 ...

  7. ReentrantLock可重入锁、公平锁非公平锁区别与实现原理

    ReentrantLock是lock接口的一个实现类,里面实现了可重入锁和公平锁非公平锁 ReentrantLock公平锁和不公平锁实现原理 公平锁会获取锁时会判断阻塞队列里是否有线程再等待,若有获取 ...

  8. Java并发包源码学习系列:ReentrantLock可重入独占锁详解

    目录 基本用法介绍 继承体系 构造方法 state状态表示 获取锁 void lock()方法 NonfairSync FairSync 公平与非公平策略的差异 void lockInterrupti ...

  9. java ReentrantLock可重入锁功能

    1.可重入锁是可以中断的,如果发生了死锁,可以中断程序 //如下程序出现死锁,不去kill jvm无法解决死锁 public class Uninterruptible { public static ...

随机推荐

  1. 『忘了再学』Shell基础 — 6、Bash基本功能(输入输出重定向)

    目录 1.Bash的标准输入输出 2.输出重定向 (1)标准输出重定向 (2)标准错误输出重定向 (3)正确输出和错误输出同时保存 3.输入重定向 1.Bash的标准输入输出 我们前边一直在说,在Li ...

  2. 【freertos】007-系统节拍和系统延时管理实现细节

    前言 本章节的时钟系统节拍主要分析FreeRTOS内核相关及北向接口层,南向接口层不分析. 本章节的系统延时主要分析任务系统延时实现. 原文:李柱明博客:https://www.cnblogs.com ...

  3. 5_系统的可控性_Controllability

  4. Architecture Review Board

    Architecture Review Board What's an Architecture Review? Architecture design is not a one-time final ...

  5. HTML5 版的flappy bird

    Flappy Bird这款简单的小游戏累计下载量已经超过5000万次,每天收入至少5万美元.然而,2月10日其开发者Dong Nguyen却将Flappy Bird从苹果App Store和Googl ...

  6. 如何用vue打造一个移动端音乐播放器

    写在前面 没错,这就是慕课网上的那个vue音乐播放器,后台是某音乐播放器的线上接口扒取,虽然这类项目写的人很多,但不得不说这还是个少有的适合vue提升的好项目,做这个项目除了想写一个比较大并且功能复杂 ...

  7. HTML表格CSS美化

    效果展示 style.css html{ width: 100%; height: 100%; overflow: hidden;}body{ width: 100%; height: 100%; f ...

  8. oracle查询出现科学计数法问题

  9. MySQL发展历史

    MySQL(发音为"my ess cue el")是一种关系型数据库管理系统, MySQL数据库管理系统由瑞典的DataKonsultAB公司研发,该公司被Sun公司收购,现在Su ...

  10. 2.Docker容器学习之新生入门必备基础知识

    0x02 Docker 核心概念 描述:Docker的三大核心概念镜像/容器和仓库, 通过三大对象核心概念所构建的高效工作流程; 1.镜像 [image] 描述:images 类似于虚拟机镜像,借鉴了 ...