Java多线程中的内存可见性
刚刚看了一下synchronized和volatile的区别,这里做一下笔记。
多线程中内存是如何分配的?
分为主内存和线程内存,当线程与其他线程共享一个变量时,便会把主内存的变量复制到线程内存中去。当发生对变量的修改时,会同步到主内存,主内存再同步到其他线程内存中去。
Synchronized实现可见性
JMM对Synchronized规定:
线程加锁时,将清空线程内存中共享变量的值,从而使用共享变量时从主内存中重新读取新值。
线程解锁前,必须把共享变量的最新值刷新到主内存中。
线程执行互斥代码过程:
1、 获得互斥锁
2、 清空线程内存
3、 从主内存中拷贝最新副本到线程内存
4、 执行代码
5、 将更改后的变量刷新到主内存
6、 释放互斥锁
指令重排序:代码书写的顺序和实际执行的顺序不同,目的是提高程序的性能。
编译器优化重排序:编译器重新排序
指令级并行优化从排序:CPU并行执行时优化
内存系统从排序:读写缓存的优化
as-if-serial:无论如何重排序,程序执行的结果都应该与代码顺序执行的结果一致。
java编译器保证as-if-serial,但是在多线程程序中并不能保证顺序执行。
Volatile实现可见性
加入内存屏障和禁止重排序优化来实现,会在volatile写操作后加入store屏障指令,读操作前加入load屏障指令。
Volatile不能保证变量操作的原子性
Lock实现可见性
Lock lock = new ReentrantLock();
lock.lock();
try{
}finally{
lock.unlock();
}