volatile

作者: 奔波儿灞_q | 来源:发表于2020-11-26 15:31 被阅读0次

1.禁止指令重排序

``
public class VoliatlieTest3 {

private volatile VoliatlieTest3 singleInstace;

private VoliatlieTest3() {
}

public VoliatlieTest3 getSingleInstace() {
    if (singleInstace == null) {            
        synchronized (VoliatlieTest3.class) {
            if (singleInstace == null) {
                singleInstace = new VoliatlieTest3();
            }
        }
    }
    return singleInstace;
}

}
``
singleInstace = new VoliatlieTest3()
这个代码分3个指令:
1.分配内存空间
2.初始化对象
3.将singleTon指向分配的内存
第二步和第三步可能会次序不一样

那么多线程这里会出问题
现在有线程A,B
如果A线程运行到singleInstace = new VoliatlieTest3(),并且这里指令被重新排序了,现在执行执行了
1.分配内存空间
2.将singleInstace指向分配的内存
执行到这里的时候singleInstace就!= null了,但实际还是空的
这个时候线程B正好过来了,判断singleInstace 不为空,然后返回了,此时B线程返回的就是空的对象

2.保证对象(基本数据类型)可见性,

``
public class VoliatlieTest2 extends Thread {

//这里  volatile 会使线程内存中的变量从主内存中获取flat,如果没有这个关键字,则下面的进程不会退出,每次打印的i都是不一样的;
volatile boolean flat = false;
int i = 0;

@Override
public void run() {
    while (!flat) { i++; }
}

public static void main(String[] args) {
    VoliatlieTest2 voliatlieTest2 = new VoliatlieTest2();
    voliatlieTest2.start();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    voliatlieTest2.flat = true;
    System.out.println(voliatlieTest2.i);
    System.out.println(voliatlieTest2.i);
}

}
``
主线程里面,flat 初始值是false, i初始值是0
子线程voliatelieTest2启动起来后,如果flat是false对i进行++,主线程休眠1秒主线程将flat改为true
打印2次i的变量
这里虽然将flat改为true了,但是子线程还会对执行i++,可以理解为子线程操作的是自己内存中的那个flat, 没有和主线程中的flat进行同步,主线程的flat被改为true了 但是子线程读取的flat还是flase,如果flat用volatile修饰,主线程将flat改为true后,子线程读取的flat就会是true 也就是i++就不会再执行了,打印的值就是相同的数

相关文章

网友评论

      本文标题:volatile

      本文链接:https://www.haomeiwen.com/subject/vxtziktx.html