深入Volatile 底层原理
- 基于CPU的嗅探机制
- 当某个线程对变量进行修改时,会立马Sync回主内存,然后再执行后面其他逻辑
- 执行Store数据,过总线时,会触发MESI缓存一致性协议,其他线程会嗅探到改值发生了变化
- 一旦xiutan到后,将会让自己工作内存空间中的数据失效
- 其他线程内的数据失效后,将会重新从主内存中获取最新的数据
- 底层通过汇编语言lock指令实现
- 如何打印java代码对应的汇编代码?下一个包,丢到jre下,配置下idea运行的jre,然后配置一串参数,再运行下程序即可打印
- 查到volatile 变量赋值 对应汇编指令后,去查汇编手册
- 再底层就是硬件级别的实现了
- volatile把早期实现在主内存的加锁的操作,移到了store、Sync数据之前,思考为什么?让锁的粒度变到更小,更轻
- volatile 能解决 可见性和时序性,但保证不了原子性
- 可以跑一个下面的示例代码看看效果,多个线程同时循环自增某个修饰的int值,看看结果
- 因为同时多读多写,过程中可能导致某个线程+1操作,最后因为嗅tan到其他线程修改值,会失效(丢失)
手写Sync锁
- 加锁、阻塞、判断锁是否被释放
- 核心:CAS设计理念、AQS抽象Sync队列
- AQS基于硬件源语实现
- 未获取到锁,使用死循环+LockSupport.park阻塞当前线程
- 使用一个安全的队列,保存线程列表
- 加锁失败,放入上面的安全队列
- 被阻塞的线程,得让获取到锁的线程来唤醒
- 解锁:比较并交换,设置锁为null,从线程队列中拿到下一个线程,通过LockSupport.unpark进行唤醒
- 解锁前,需要判断时加锁线程才能解锁
- 公平与非公平:公平与非公平,非公平一上来就抢锁,公平锁是先来的先排队
ReentrantLock
- 实现了重入与不可重入,公平与非公平
- 可重入:锁是可反复持有,通过信号量记录加锁次数,加多少次,就要解多少次;什么场景用得到?
- 具体可看下源码及AQS类结构
- Node 类 是实现公平与非公平的核心,主要处理排队机制,CLH队列可以了解下