Volatile 关键字提供的可见性

/**
 * 类说明:演示Volatile的提供的可见性
 */
public class VolatileCase {
    // 说明:当ready没有volatile修饰时,执行结果是PrintThread线程一直处于被挂起状态,子线程感知不到主线程中的变量
    // 当ready被volatile修饰时,保证了ready的可见性,所以子线程感知到了主线程变量的值从而结束子线程,继续执行主线程
    private static boolean ready;
    // private volatile static boolean ready;
    private static int number;

   
    private static class PrintThread extends Thread {
        @Override
        public void run() {
            System.out.println("PrintThread is running.......");
            while (!ready) ;//无限循环
            System.out.println("number = " + number);
        }
    }

    public static void main(String[] args) {
        new PrintThread().start();
        SleepTools.second(1);
        number = 51;
        ready = true;
        SleepTools.second(5);
        System.out.println("main is ended!");
    }
}

执行结果:

PrintThread is running.......
main is ended!

说明:PrintThread子线程未执行完被挂起,主线程执行完毕。这是因为子线程在执行时拿到的ready默认值是false,子线程感知不到下面语句对ready的重新赋值,所以一直在无限循环。

当用volatile修饰后:

private volatile static boolean ready;

再次执行:

PrintThread is running.......
number = 51
main is ended!

说明:子线程感知到主线程的变量ready变为了true,从而跳出循环,执行完成。这就是volatile关键字的作用---可见性。

volatile的缺点:它只保证可见性,不能保证在并发下的原子性。

什么是不能保证原子性?

就是多线程下,多个线程都可以对其修饰的变量或者对象进行修改,就像没有加synchronized一样,都可以进行修改。造成前后读到的值不一致。

volatule 适用场景:一写多读。就是一个线程在写,其他线程都是读取的情况。

你可能感兴趣的:(java,开发语言)