volatile关键字

volatile的可见性

通知OS(操作系统)底层,在CUP计算的过程中,都要检查内存中数据的有效性,保证最新的内存数据被使用
下面先看一段代码:

public class TestSync { 
    
    /* volatile */ boolean b = true;
    
    void m() {
        System.out.println("start");
        while (b) {  //死循环
        }
        System.out.println("end");
    }
    public static void main(String[] args) {
        TestSync t = new TestSync();
        new Thread(new Runnable() {
            @Override
            public void run() {
                t.m();  //先启动一个线程调用 m()
            }
        }).start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.b = false;   //1 秒钟过后 将b 置为false  理想情况下会打印 end
        
        //如果 将 volatile 关键字 注释掉 那么运行时 将只打印 start 而不打印end 程序在此处卡死(可能会让你的电脑cup沾满哦)
        //加上 volatile 后 先打印start 1s后打印end
        
        //原因: volatile 可见性通知OS操作系统底层,在CPU计算过程中,都要检查内存中数据的有效性。保证最新的内存数据被使用。
        // CPU在计算时 ,会将一些数据缓存,这里的 b 就被缓存了, 每次计算时都直接取缓存中的数据,所以会一直取到true
        //加上 volatile后 程序调用的时候 每次都会去内存(数据装载在内存中,也就时这个 b )中去看下数据是否有改变,保证取到最新的数据来计算
    }
}

volatile 只保证可见性,不能保证原子性;不是加锁问题,只是内存数据可见

public class TestSync { 
    volatile int count = 0;
    /*synchronized*/ void m(){
        for(int i = 0; i < 10000; i++){
            count++;
        }
    }
    
    public static void main(String[] args) {
         TestSync t = new TestSync();
        List threads = new ArrayList<>();
        //创建了10个线程放到 list中
        for(int i = 0; i < 10; i++){
            threads.add(new Thread(new Runnable() {
                @Override
                public void run() {
                    t.m();
                }
            }));
        }
        
        //然后遍历启动线程
        for(Thread thread : threads){
            thread.start();
        }
        for(Thread thread : threads){
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //理论上 这里的 count 应该是 10* 10000 = 100000,但实际情况却少的多(在m2()方法不加 synchronized 关键字的时候)
        //加上 synchronized  就是100000
        //也就可以看出 volatile, 只能保证可见性,不能保证原子性。
        System.out.println(t.count);
    }
}

你可能感兴趣的:(volatile关键字)