JVM之高效并发
- 硬件的效率以及一致性
- 由于计算机的存储设备与处理器的处理速度差距很大;因此引入了高速缓存,平衡它们之间的速度差异
- 引入高速缓存所带了的问题:缓存一致性(如:MSI,MESI,MOSI)
- 如何解决缓存一致性:引入缓存一致性协议;处理器在进行读写时遵循一致性协议
- 主存、告诉缓存、处理器之间的关系模型:
- JVM中线程、工作内存、主存的关系:
- volatile(保证了可见性、有序性)关键字
- volatile可以保证变量的可见性;以及防止指令重排
- 可见性:当一个线程修改了某变量时,其余线程会立即知道
- 指令重排序(JVM的优化操作):保证结果正确的情况下,代码执行的顺序不会与编码一致(例如:-1+4+7=10;4-1+7=10;7+4-1=10;)
- 三大特性
- 原子性:除了long、double类型其余数据类型均的访问、读写均是原子性
- 可见性:指当一个线程修改了共享变量的值时,其他线程能够立即得知这个修改
- 有序性:单线程下均是有序的,多线程可能发生指令重排序、工作内存与主存同步延迟
- 先行发生原则(Happens-Before)
- 是判断数据是否存在竞争、线程是否安全的依据
- 指若A先于B,则A的任何操作都是必须被B知道的;也就是说A的任何数据对于B来说,都必须是最新的;
- HB原则与时间不存在任何因果关系(指令重排序),一切以HB原则为准
线程安全的实现方法
- 互斥同步(悲观策略)
- synchronized关键字:synchronized持有需要封锁的引用数据类型,属于可重入锁;在经历字节码编译后,会形成monitorenter和monitorexit这两个字节码指令
- synchronized持有锁是一个重量级操作,对于线程的阻塞以及唤醒需要依赖操作系统,存在着操作系统用户态到核心态的转换,性能损耗较高;** 但是在JDK6.0加入了大量优化synchronized的操作**
- synchronized特性:可重入、非公平、无法强制释放锁
- ReentrantLock(可重入锁):ReentrantLock是Lock接口的实现,支持以非代码形式同步
- ReentrantLock特性:可重入、可中断、支持多条件加锁
- synchronized与Lock对比:
- Lock需要手动释放锁;
- synchronized实现锁清晰、简单;
- 非阻塞同步(乐观策略)
- CAS(Compare and Swap)
- CAS需要三个操作数:内存地址、期望值、新的值;当且仅当期望值与内存地址一致时,才做出修改
- ABA问题:指一个数由A变为B又变为A的过程,误以为CAS正确,从而修改值
- 解决策略:引入时间戳、版本号;(如:AtomicStampedReference)