大家好,又见面了,我是你们的朋友全栈君。
1、一个变量声明为volatile,就意味着这个变量被修改后其他所有使用到此变量的线程都立即可见
2、禁止指令重排序,防止在运行时不是按照代码的先后顺序执行
volatile是一种轻量级的同步机制,不会引起的线程上下文切换,可以保证可见性和禁止重排序,但不能保证原子性带来的线程安全问题。
volatile特性
可见性
当有多个线程访问同一个变量时,一个线程对此变量的修改,其他线程应该立刻可获取到修改后的值。
一个变量用volatile修饰后,当对此变量写入时,会立刻将写入后的值刷新到主存中,并且将其他线程本地内存中保存的值失效,其他线程读取此变量时,会直接从主内存中读取。
public class VolatileDemo {
private static boolean stop = true;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
while(stop){//无限循环
}
}).start();
//确保上面线程先执行
Thread.sleep(100);
//虽然修改为false,但是上面线程依旧不会停
stop = false;
System.out.println("main thread end...");
}
}
这就是可见性问题,只需要加上volatile修饰符即可。【亲测,确实是!】
private volatile static boolean stop = true;
指令重排序
编译器有时会为了效率,在保证不影响最终结果的前提下,会改变代码的执行顺序。
在单线程下,不会存在问题,但是在多线程下就会带来一些问题,比如单例模式中,双重锁校验,锁的对象必须用volatile修改。
单例模式:双重锁校验
public class DoubleCheck {
private static volatile DoubleCheck doubleCheck = null;
private DoubleCheck() {
}
public static DoubleCheck getInstance() {
//第一次校验
if (doubleCheck == null) {
synchronized (DoubleCheck.class) {
//第二次校验
if (doubleCheck == null) {
doubleCheck = new DoubleCheck();
}
}
}
return doubleCheck;
}
}
doubleCheck = new DoubleCheck();可以分解为3行伪代码
1、memory = allocate() //分配内存
2、ctorInstanc(memory) //初始化对象
3、doubleCheck = memory //设置doubleCheck指向刚分配的地址
转自:https://blog.csdn.net/CSDN_WYL2016/article/details/107006025
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/161271.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...