是对之前java并发的一个补充。:P
java的操作都是将数据从主内存加载到工作内存去做操作,为了保证线程的安全归定了几个原子性操作。
java的几个原子性操作
- read:主内存,将数据从主内存传输到工作内存,以便load使用
- load:工作内存,将read的变量副本放入到工作内存中
- assign:工作内存,赋值操作。将执行引擎(jvm)中的值赋值给变量。
- use:工作内存,把工作内存中的值传递给执行引擎。
- store:工作内存,将数据传输到主内存中,以便write操作使用
- write:主内存,将数据写入到主内存中。
- lock:主内存,将变量标识为线程独占
- unlock:主内存,释放锁标记,标识变量变为共享状态。
几个规定
- read和load,store和write成对出现,并且先后顺序不能改变
- assign必须在load之后,且assign之后必须写会主内存,且加载到内存的变量必须assign
- use、store之前必须assign,load
- lock操作后工作内存会被清空
- unlock必须在lock之后,且unlock必须等待变量别写会主内存。
保证线程安全的3个要点
- 原子性:8个原子操作
- 可见性:voltile、final、synchrozied可以保证
- 顺序性:voltile、synchrozied
线程实现
1:1模型:使用内核线程,实现简单,但是无法支持高并发因为内核态和用户态消耗大,并且由于是1:1无法支持高并发。
1:N:使用用户线程,可支持高并发,但是调度等实现难度大。
N:M:用户线程用于并发,内核线程用于调度。综合上面俩种优缺点。
线程状态
new:new一个线程
run:执行start
block:synchronized
wait:没有参数的wait
time_waiting:有参数的wait和sleep
jvm的锁优化
由于锁需要从用户态转到内核态作为控制,所以采用如下几种优化方案。
- 锁消除:通过逃逸分析发现没有变量逃逸的情况,会去掉锁。
- 锁粗化:如果多一个对象反复加锁、解锁会考虑合并
- 偏向锁:如果当前线程获取锁,复制markword,markword修改锁标记位,以及获取锁线程的线程ID;
- 轻量级锁:如果遇到竞争,复制markword,markword修改锁标记位,以及锁的lockrecord地址。