高效并发
java内存模型(JMM)
抽象模型,并非真实存在。模仿处理器-高速缓存-主内存
java内存模型定义了8种操作,将变量从主内存拷贝到工作内存,分别为:
作用于主内存的变量
- lock :标识为一条线程独占的状态
- unlock:释放被lock的变量,此时才可以被其他线程Lock
- read:将变量传输到线程的工作内存中,以便之后的load使用
- write:把store操作从工作内存中得到的变量的值放入主内存的变量中
作用于工作内存的变量
- load:把read到的变量,存入到线程本地变量
- use:将变量值传给执行引擎,每当虚拟机遇到需要使用该变量的字节码则执行此操作
- assign:将执行引擎接收到的值赋值给工作内存的变量
- store:把工作内存中的变量传到主内存中
volatile型变量
最轻量级的同步机制,线程不安全
- 对所有线程可见:本地线程变量会同步到主内存,但并非立即,即非原子性
- 禁止指令重排序优化,增加内存屏障(指令重排序不能把后面的指令排序到内存屏障之前)
特殊规则
原子性、可见性、有序性、先行发生原则
Java与线程
- 内核线程
- 用户线程
- 用户线程加轻量级进程混合实现
用户线程加轻量级进程混合实现
当下高级语言均采用此种方式实现进程。单独使用用户进程,会遇到许多诸如“阻塞如何处理”,“线程映射到其他处理器上”的问题以致难以处理或无法处理。
- 协同调度
- 抢占式线程调度
协同调度
执行时间由线程本身控制,线程执行完毕后主动通知切换到另一个线程上。实现简单,不存在线程同步问题。但线程时间不可控。
抢占式线程调度
由系统分配执行时间,线程时间可控,调度过程耗费资源。
线程安全
对象锁
synchronized 重量级锁
ReentrantLock 重入锁
- 等待可中断
- 公平锁
- 锁绑定多个条件
互斥同步
- 阻塞同步-悲观锁
- 非阻塞同步-乐观锁
无同步方案
- 可重入代码-不依赖任何公共资源
- 线程本地储存
锁优化
自旋锁与自适应锁
线程的挂起和恢复需要切换到内核态执行,造成大量开销,为了避免短时间锁的等待,线程采用while循环自旋,自旋默认次数是10次。自适应自旋锁可以根据锁的情况调节次数。
锁消除
不必要的同步块会自动被忽略掉
锁粗化
对于零碎的加锁,解锁操作会增大开销,jvm会自动将锁的范围扩大