Chiriri's blog Chiriri's blog
首页
  • Java

    • JavaSE
    • JavaEE
    • 设计模式
  • Python

    • Python
    • Python模块
    • 机器学习
  • Golang

    • Golang
    • gRPC
  • 服务器

    • Linux
    • MySQL
    • NoSQL
    • Kubernetes
  • 项目

    • 传智健康
    • 畅购商城
  • Hadoop生态

    • Hadoop
    • Zookeeper
    • Hive
    • Flume
    • Kafka
    • Azkaban
    • Hbase
    • Scala
    • Spark
    • Flink
  • 大数据项目

    • 离线数仓
  • 青训营

    • 第四届青训营
  • HTML

    • HTML
    • JavaScript
  • Vue

    • Vue2
    • TypeScript
    • Vue3
    • Uni-APP
  • 数据结构与算法
  • C语言
  • 考研数据结构
  • 计算机组成原理
  • 计算机操作系统
  • Java基础

    • Java基础
    • Java集合
    • JUC
    • JVM
  • 框架

    • Spring
    • Dubbo
    • Spring Cloud
  • 数据库

    • MySQL
    • Redis
    • Elasticesearch
  • 消息队列

    • RabbitMQ
    • RocketMQ
  • 408

    • 计算机网络
    • 操作系统
    • 算法
  • 分类
  • 标签
  • 归档
  • 导航站
GitHub (opens new window)

Iekr

苦逼后端开发
首页
  • Java

    • JavaSE
    • JavaEE
    • 设计模式
  • Python

    • Python
    • Python模块
    • 机器学习
  • Golang

    • Golang
    • gRPC
  • 服务器

    • Linux
    • MySQL
    • NoSQL
    • Kubernetes
  • 项目

    • 传智健康
    • 畅购商城
  • Hadoop生态

    • Hadoop
    • Zookeeper
    • Hive
    • Flume
    • Kafka
    • Azkaban
    • Hbase
    • Scala
    • Spark
    • Flink
  • 大数据项目

    • 离线数仓
  • 青训营

    • 第四届青训营
  • HTML

    • HTML
    • JavaScript
  • Vue

    • Vue2
    • TypeScript
    • Vue3
    • Uni-APP
  • 数据结构与算法
  • C语言
  • 考研数据结构
  • 计算机组成原理
  • 计算机操作系统
  • Java基础

    • Java基础
    • Java集合
    • JUC
    • JVM
  • 框架

    • Spring
    • Dubbo
    • Spring Cloud
  • 数据库

    • MySQL
    • Redis
    • Elasticesearch
  • 消息队列

    • RabbitMQ
    • RocketMQ
  • 408

    • 计算机网络
    • 操作系统
    • 算法
  • 分类
  • 标签
  • 归档
  • 导航站
GitHub (opens new window)
  • JavaSE

  • JavaEE

  • Linux

  • MySQL

  • NoSQL

  • Python

  • Python模块

  • 机器学习

  • 设计模式

  • 传智健康

  • 畅购商城

  • 博客项目

  • JVM

  • JUC

    • 多线程
    • CompletableFuture
    • 锁
    • LockSupport与线程中断
    • Java内存模型之JMM
    • Volatile与Java内存模型
    • CAS
    • 原子操作类
    • ThreadLocal
    • Java对象内存布局和对象头
    • Synchronized与锁升级
    • AbstractQueuedSynchronizer之AQS
    • ReentrantLock、ReentrantReadWriteLock、StampedLock讲解
    • JUC总结
      • CompletableFuture
      • “锁”事儿
      • JMM
      • synchronized及升级优化
        • 锁的到底是什么
        • 无锁→偏向锁→轻量锁→重量锁
        • Java对象内存布局和对象头
        • 64位图
      • CAS
        • CAS的底层原理
        • CAS问题
        • ABA问题
      • volatile
        • 特性
        • 内存屏障
      • LockSupport
        • 是什么
        • LockSupport.park和Object.wait区别
      • AbstractQueuedSynchronizer
        • 是什么
        • 出队入队Node
      • ThreadLocal
      • 原子增强类
    • 并发集合
  • Golang

  • Kubernetes

  • 硅谷课堂

  • C

  • 源码

  • 神领物流

  • RocketMQ

  • 短链平台

  • 后端
  • JUC
Iekr
2023-12-04
目录

JUC总结

# JUC 总结

image-20231204212017693

# CompletableFuture

# “锁” 事儿

  1. 悲观锁

  2. 乐观锁

  3. 自旋锁

  4. 可重入锁(递归锁)

  5. 写锁(独占锁)/ 读锁(共享锁)

  6. 公平锁 / 非公平锁

  7. 死锁

  8. 偏向锁

  9. 轻量锁

  10. 重量锁

  11. 邮戳(票据)锁

# JMM

# synchronized 及升级优化

# 锁的到底是什么

image-20231204211813148

image-20231204211817164

  • 作用于实例方法,当前实例加锁,进入同步代码前要获得当前实例的锁;
  • 作用于代码块,对括号里配置的对象加锁。
  • 作用于静态方法,当前类加锁,进去同步代码前要获得当前类对象的锁;

# 无锁→偏向锁→轻量锁→重量锁

# Java 对象内存布局和对象头

# 64 位图

image-20231204211851608

# CAS

# CAS 的底层原理

比较并交换

//unsafe.cpp
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
  UnsafeWrapper("Unsafe_CompareAndSwapInt");
  oop p = JNIHandles::resolve(obj);
  jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
  return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END
1
2
3
4
5
6
7

JDK 提供的 CAS 机制,在汇编层级,会禁止变量两侧的指令优化,然后使用 cmpxchg 指令比较并更新变量值 (原子性)

# CAS 问题

# ABA 问题

问题: 线程 X 准备将变量的值从 A 改为 B,然而这期间线程 Y 将变量的值从 A 改为 C,然后再改为 A;最后线程 X 检测变量值是 A,并置换为 B。

但实际上,A 已经不再是原来的 A 了解决方法,是把变量定为唯一类型。值可以加上版本号,或者时间戳。

解决: 如加上版本号,线程 Y 的修改变为 A1->B2->A3,此时线程 X 再更新则可以判断出 A1 不等于 A3

# volatile

# 特性

# 内存屏障

# LockSupport

# 是什么

LockSupport 是基于 Unsafe 类,由 JDK 提供的线程操作工具类,主要作用就是挂起线程,唤醒线程。

LockSupport.park

LockSupport.unpark

# LockSupport.park 和 Object.wait 区别

线程在 Object.wait 之后必须等到 Object.notify 才能唤醒

LockSupport 可以先 unpark 线程,等线程执行 LockSupport.park 是不会挂起的,可以继续执行

# AbstractQueuedSynchronizer

# 是什么

volatile+cas 机制实现的锁模板,保证了代码的同步性和可见性,而 AQS 封装了线程阻塞等待挂起,解锁唤醒其他线程的逻辑。AQS 子类只需根据状态变量,判断是否可获取锁,是否释放锁,使用 LockSupport 挂起、唤醒线程即可

//AbstractQueuedSynchronizer.java
public class AbstractQueuedSynchronizer{
    //线程节点
    static final class Node {
        volatile Node prev;
        volatile Node next;
        volatile Thread thread;
        ...
    }    
    //head 等待队列头尾节点
    private transient volatile Node head;
    private transient volatile Node tail;
    private volatile int state;      // The synchronization state. 同步状态
    ...
    //提供CAS操作,状态具体的修改由子类实现
    protected final boolean compareAndSetState(int expect, int update) {
        return STATE.compareAndSet(this, expect, update);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 出队入队 Node

image-20231204212110456

AQS 内部维护一个同步队列,元素就是包装了线程的 Node。

同步队列中首节点是获取到锁的节点,它在释放锁的时会唤醒后继节点,后继节点获取到锁的时候,会把自己设为首节点。 线程会先尝试获取锁,失败则封装成 Node,CAS 加入同步队列的尾部。在加入同步队列的尾部时,会判断前驱节点是否是 head 结点,并尝试加锁 (可能前驱节点刚好释放锁),否则线程进入阻塞等待。

# ThreadLocal

当使用 ThreadLocal 声明变量时,ThreadLocal 为每个使用该变量的线程提供独立的变量副本, 每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本

# 原子增强类

编辑 (opens new window)
上次更新: 2023/12/13, 06:06:02
ReentrantLock、ReentrantReadWriteLock、StampedLock讲解
并发集合

← ReentrantLock、ReentrantReadWriteLock、StampedLock讲解 并发集合→

最近更新
01
k8s
06-06
02
进程与线程
03-04
03
计算机操作系统概述
02-26
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Iekr | Blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式