美文网首页
volatile关键字

volatile关键字

作者: larQ | 来源:发表于2018-10-26 00:18 被阅读0次

    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<Thread> 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关键字

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