1.Java语言层面支持的实现内存可见性的方式
synchronized
volatile
final
2.synchronized 可以实现 原子性和可见性
3.synchronized 实现可见性的代码实现过程:
1)获得互斥锁
2)清空工作内存
3)从主内存中拷贝共享变量的最新副本到工作内存
4)执行代码
5)将工作内存中更改后的共享变量的值更新到主内存
6)释放互斥锁
4.导致共享变量在内存中不可见的原因:
1)线程的交叉执行
2)线程交叉执行+重排序
3)工作内存中共享变量的值没有及时更新到主内存
5.volatile可以实现可见性,不可实现原子性
6.volatile实现可见性:
通过加入内存屏障和禁止重排序优化实现内存可见性:
1)对volatile变量执行写操作时,会在写操作后加入一条store屏障指令,将共享变量刷新到主内存
2)对volatile变量执行读操作时,会在读操作前加入一条load屏障指令,将主内存中的共享变量加载到工作内存
7.保证自增操作原子性的方法:
1)使用synchronized关键字
2)使用ReentrantLock
3)使用AtomicInteger
8.volatile适用场合
1)对变量的写入操作不依赖当前值
2)该变量没有包含在具有其他变量的不变式中
9.synchronized 和 volatile 比较
1)volatile不需要加锁,比synchronized更轻量级,不会阻塞线程
2)从内存可见性角度讲,volatile读相当于加锁,volatile写相对于解锁
3)synchronized既能保证可见性,又能保证原子性;volatile只能保证可见性,不能保证原子性。
10.对64位(long,double)变量的读写可能不是原子操作
Java内存模型允许将没有被volatile修饰的64位数据类型的读写操作划分为两次32位的读写操作进行