java多线程-可见性
定义:一个线程对主内存的修改可以及时的被其他线程观察到
共享变量在线程间不可见的原因:
① 线程交叉执行
② 线程交叉执行结合指令重排序
③ 共享变量没有在更新后的值没有在工作内存与主存之间及时更新
synchronized的两条规定
① 线程释放锁前,必须把共享变量的最新值刷新到主内存当中
② 线程获取锁时,将当前线程的本地内存置为无效,从而使用共享变 量时需要从主内存中重新读取最新的值
volatile通过内存屏障和禁止重排序以及禁止中断优化来实现(从CPU的角度去看)
① 对volatile类型变量进行写操作时,会在写操作后面加入一条store 屏障指令,将本地内存中的共享变量值刷新到主内存当中;
② 读取volatile类型变量时,会在读操作前加入一条load屏障指令,从 主内存中读取共享变量;
③ volatile变量在线程每次访问的时候都强迫线程从主内从读取变 量,而当该变量发生变化的时候又会强迫线程将最新的值刷新到主 内存中,这两个操作保证了volatile线程之间的可见性;
④ volatile只是保证了共享变量的可见性,并没有保证volatile修 饰的变量的所有操作都是原子操作。对于被volatile修饰的变量 用于get方法和set方法都是线程安全的;此时相当于在get和set 方法上面添加了synchronized关键字。但是对于非原子操作的就 不是线程安全的方法;
⑤ volatile适合用于作为检查某个状态标记量以判断是否退出循环 和双重检测机制(安全单例模式)
Synchronized volatile关键字,volatile修饰基本数据类型和自定义类型区别,volatile底层实现
volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
volatile标记的变量不会被编译器优化(指令重排);synchronized标记的变量可以被编译器优化