JAVA并发
2025-08-01 15:43:57 3 举报
AI智能生成
本文档深入探讨了Java中的并发编程技术,涵盖了从基础到高级的多个核心概念。首先介绍了Java并发包(java.util.concurrent)中的核心类,如Executor框架、线程池、并发集合及原子变量。随后,解析了同步机制,包括synchronized关键字和Lock接口的使用以及它们的区别和适用场景。接着,文档详解了线程通信机制,如wait()、notify()和notifyAll()的原理及其使用方法。此外,对并发性能优化策略进行了分析,探讨了避免死锁、减少锁竞争和利用线程池管理的最佳实践
作者其他创作
大纲/内容
面试问题
1、为什么程序计数器是私有的
程序计数器记录当前线程执行代码的位置
2、虚拟机栈和本地方法栈为什么是私有的
确保线程中的局部变量表和操作数栈,常量池引用不被其他线程更改
3、并行和并发
并行
单位时间内,同时运行
并发
同一时段,多个任务都在运行
4、为什么要用多线程
系统最小调用单位,轻量级进程,减小调用成本
曾大并发量,出现等待任务的时候,可以使用多线程提高并发
CPU核数越来越多,硬件对多线程支持越来越好
5、多线程存在的问题
数据不安全
死锁
内存泄漏
6、上下文切换
让出CPU
时间片
中断
停止
7、如何避免死锁
银行家算法
8、synchronized关键字
配合volatile实现安全单例
9、lock和synchronized的区别
等待可中断
实现公平锁
通知机制
lock可以绑定多个监听器
java内存模型
happen before
happen-before的传递性原则
线程启动的happen-before原则
线程中断的happen-before原则
线程终结的happen-before原则
对象创建的happen-before原则
volatile的happen-before原则
锁的happen-before原则
锁的happen-before原则
数据流向
主内存空间
用户空间
load
read
store
write
Volatile
指令重排序
数据可见性
写可见
锁
对象锁
对对象加锁
类锁
对类对象加锁
乐观锁
不加锁的特点能够使其读操作的性能大幅提升
自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据
CAS算法
循环时间长开销大
Compare And Swap(比较与交换)
ABA问题
自旋锁
适应性自旋锁
悲观锁
先加锁可以保证写操作时数据正确
自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改
synchronized
monitorenter/monitorexit
mark word
hashCode
分代年龄
是否式偏向锁
锁标志位
偏向锁
线程id
Epoch
年龄
1
01
出现竞争,升级为轻量级锁
根据存储线程id
轻量级锁
栈中记录的指针
30
锁标记
2
CAS修改mark word
失败,膨胀为重量级锁
重量级锁
指向互斥量指针
30
锁标记
2
森亏瑞纳斯的
Lock
AQS
同步队列
等待状态
cancelled
被中断,超时
signal
竞争获胜需要唤醒
condition
在condition队列中等待
propagate
后续节点传播唤醒操作,共享模式下使用
initial
前驱
后继
线程引用
等待线程的后继节点
获取同步状态
头节点释放同步状态后,唤醒后继节点
FIFO原则
同步状态
Condition
锁监视器
等待对列
结构与同步队列类似
await
将获得锁的节点构成新节点加入等待队列
sginal
将等待队列首节点加入同步队列尾部
LockSupport
与synchronized对比
非阻塞得获取锁
被中断得获取锁,中断可以释放锁
超时获取锁
Reentrantlock
可重入与不可重入
可重入锁
非可重入锁
公平与非公平
公平锁
CPU唤醒阻塞线程的开销比非公平锁大
吞吐效率相对非公平锁要低
等待锁的线程不会饿死
多个线程按照申请锁的顺序来获取锁,线程直接进入队列中排队,队列中的第一个线程才能获得锁
非公平锁
多个线程加锁时直接尝试获取锁,获取不到才会到等待队列的队尾等待
性能更高,往往才获得锁的线程更容易获得锁
ReetrantReadWriteLock
读锁
共享锁
写锁
独享锁
锁降级
1、写锁获取锁
2、获取读锁
3、释放写锁
保证数据可见性
原子操作
术语
内存顺序冲突
多个CPU同时修改一个缓存行中不同的数据,导致CPU流水线清空执行。
CPU流水线
加快执行
CAS
旧值和新值
原子操作
总线加锁
缓存加锁
原子操作类
线程
线程通信
线程池
状态
新建
等待
无限等待
有限等待
wait
join
parkNanos
parkUnitl
阻塞
运行
停止
OS
初始状态
可运行状态
可运行
运行状态
可运行
休眠状态
Blocked、Waiting、Time_Waiting
终止状态
测试
子主题
实现
内核---轻量级进程
java
用户线程
用户线程与轻量级进程
调度
抢占式线程调度
系统控制时间
可以让出时间
设置线程级别
协同式线程调度
执行时间自己控制
执行时间不可控,容易阻塞
实现简单
TheadLocal
引用
强引用
软引用
弱引用
虚引用
结构
键值是TheadLocal的虚引用
子主题
每个线程持有ThreadLocalMap
一个用来存出
子主题
流程
register一些native 方法,start0,stop0
然后执行了start0
其实就是去调用JVM里面的方法了,应该叫啥 startThread的,这个时候就去启动一个 OS级别的真实线程
这个这个OS级别线程启动之后,会通过JVM的一个叫什么 run_method 的方法,来回调 run() 方法
run,其实就是一个回调方法,被JVM里面的方法回调而已
Unsafe
基本介绍
Unsafe 类为一单例实现
功能介绍
内存操作
堆外内存的分配、拷贝、释放、给定地址值操作
allocateMemory
reallocateMemory
freeMemory
setMemory
copyMemory
getObject
获取给定地址值,忽略修饰限定符的访问限制。与此类似操作还有getInt, getDouble,
getLong, getChar
getLong, getChar
putObject
为给定地址设置值,忽略修饰限定符的访问限制,与此类似操作还有 :
putInt,putDouble,putLong, putChar
putInt,putDouble,putLong, putChar
getByte
putByte
使用堆外内存的原因
对垃圾回收停顿的改善
提升程序 I/O 操作的性能
典型应用
DirectByteBuffer
Netty、MINA 等 NIO 框架
Cleaner
Unsafe.allocateMemory
Unsafe.setMemory
Deallocator
清理时释放
CAS
内存位置、预期原值及新值
CAS 是一条 CPU 的原子指令
(cmpxchg 指令)
compareAndSwapObject
o
offset
expected
update
compareAndSwapInt
compareAndSwapLong
典型应用
atomic 相关类
Java AQS
CurrentHashMap
AtomicInteger
valueOffset
字段 value 的内存偏移地址
Unsafe.objectFieldOffset(field)
Class 相关
静态字段内存定位、定义类、定义匿名类、检验 & 确保初始化
staticFieldOffset
staticFieldBase
shouldBeInitialized
ensureClassInitialized
defineClass
defineAnonymousClass
典型应用
JDK 使用 invokedynamic 及 VM Anonymous Class 结合来
实现 Java 语言层面上的 Lambda 表达式
实现 Java 语言层面上的 Lambda 表达式
invokedynamic
运行动态语言
VM Anonymous Class
一种模板机制
无需通过 ClassClassLoader 进行类加载且更易回收
匿名类不显式挂在任何 ClassLoader
Lambda 表达式实现
通过 invokedynamic 指令调用引导方法生成调
用点
通过 ASM 动态生成字节码
利用 Unsafe 的 defineAnonymousClass 方法定义实现相应的函数式接口的匿名类
再实例化此匿名类
返回与此匿名类中函数式方法的方法句柄关联的调用点
通过此调用点实现调用相应 Lambda 表达式定义逻辑的功能
对象操作
objectFieldOffset
getObject
获得给定对象的指定地址偏移量的值,与此类似操作还有: getInt, getDouble, getLong
putObject
给定对象的指定地址偏移量设值,与此类似操作还有: putInt, putDouble, putLong,putChar 等
getObjectVolatile
从对象的指定偏移量处获取变量的引用,使用 volatile 的加载语义
putObjectVolatile
存储变量的引用到对象的指定的偏移量处,使用 volatile 的存储语义
putOrderedObject
有序、延迟版本的 putObjectVolatile 方法,不保证值的改变被其他线程立即看到。只
有在 field 被 volatile 修饰符修饰时有效
allocateInstance
绕过构造方法、初始化代码来创建对象
典型应用
常规对象实例化方式
非常规的实例化方式
allocateInstance
不需要调用其构造函数、初始化
代码、JVM 安全检查等
代码、JVM 安全检查等
抑制修饰符检测
Gson
Objenesis
java.lang.invoke
线程调度
线程挂起
park
恢复
unpark
锁机制
monitorEnter
monitorExit
tryMonitorEnter
典型应用
AbstractQueuedSynchronizer
LockSupport.park()
LockSupport.unpark()
系统信息获取
addressSize
pageSize
内存屏障
内存栅栏,内存栅障,屏障指令
避免代码重排序
loadFence
禁止 load 操作重排序
storeFence
禁止 store 操作重排序
fullFence
禁止 load、 store 操作重排序
典型应用
StampedLock
读写锁的一个改进版本
乐观读锁的实现
完全不会阻塞写线程获取写锁
缓解读多写少时写线程“饥饿”现象
两阶段锁保证一致性
获取乐观读锁
copy变量到工作内存
检验锁状态
获取悲观读锁
copy变量到工作内存
释放悲观读锁
线程本地计算
数组操作
arrayBaseOffset
返回数组中第一个元素的偏移地址
arrayIndexScale
返回数组中一个元素占用的大小
典型应用
AtomicIntegerArray
线程池
0 条评论
下一页