Java内存模型
共享内存模型指的就是Java内存模型(简称JMM),JMM决定一个线程对共享变量的写入时,能对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。
什么是Java内存模型:java内存模型简称jmm,定义了一个线程对另一个线程可见。共享变量存放在主内存中,每个线程都有自己的本地内存,当多个线程同时访问一个数据的时候,可能本地内存没有及时刷新到主内存,所以就会发生线程安全问题。
Volatile关键字
可见性也就是说一旦某个线程修改了该被volatile修饰的变量,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,可以立即获取修改之后的值。
在Java中为了加快程序的运行效率,对一些变量的操作通常是在该线程的寄存器或是CPU缓存上进行的,之后才会同步到主存中,而加了volatile修饰符的变量则是直接读写主存。
使用场景:
只要全局共享变量,都可加上volatile关键字,及时刷新到主内存
特性:
1. 禁止了指令重排序
2. 操作具有可见性,不具有原子性
Volatile与Synchronized区别
(1)从而我们可以看出volatile虽然具有可见性但是并不能保证原子性。
(2)性能方面,synchronized关键字是防止多个线程同时执行一段代码,就会影响程序执行效率,而volatile关键字在某些情况下性能要优于synchronized。
但是要注意volatile关键字是无法替代synchronized关键字的,因为volatile关键字无法保证操作的原子性。
重排序
CPU对代码实现优化不会对有依赖关系型做重排序,
重排序: 使得代码的执行顺序可能发生改变,但是执行结果不会发生改变
规则:as-if-serial: 不管怎么冲排序不会影响执行结果, 目的: 为了提高并行度
重排序对多线程的影响
class demo{
int a = 0;
boolean flag = false;
public void writer() {
a = 1; //1
flag = true; //2
}
Public void reader() {
if (flag) { //3
int i = a * a; //4
}
}
public static void main(String[] args) {
// 读和写分别模拟不同的线程在操作
}
}
因为1 、 2 之间没有依赖关系,可能1、2的执行顺序会发生改变,此时多线程环境下,
a的值可能就为1. 或者0 , 导致发生错误,
解决方法:
在 变量a 加上volatile关键字: 它可以防止重排序的发生。