1.背景
在java的内存模型中,每个线程都有自己的工作内存,同时还共享一个主内存。假如说有两个线程要读取同一个变量的时候,首先需要把值放到自己工作内存中,这样执行的时候就可以直接使用缓存值了 不需要读取主内存中的值了,但是这样有一个问题就是多线程的时候,其中一个线程修改了值之后无法同步到其他线程中,所以需要修改之后刷到主内存中去,这就是可见性
volatile关键字:
可见性:
1.当线程1修改了变量之后会强制刷新主内存中的值,
2.如果有其他线程有使用这个变量,就会强制让其他线程工作内存中的这个值时效
3.如果其他线程想使用,只能重新加载最新值
指令重排序
指令重排是指编译器和处理器为了优化程序性能对指令序列进行重新排序
重排序分3种类型。
1)编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。
2)指令级并行的重排序。现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
3)内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行
简而言之就是如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性。重排序呢就会产生结果错误,不会指令重排,假如两个方法没有依赖关系 就有可能指令重排,在多线程的时候就会产生错误
指令重排详细情况需要查看jmm多线程内存模型