zoukankan      html  css  js  c++  java
  • Java并发编程(二):volatile关键字

    volatile是Java虚拟机提供的轻量级的同步机制。volatile关键字有如下两个作用,一句话概括就是内存可见性和禁止重排序。
    1)保证被volatile修饰的共享变量对所有线程总是可见的,也就是当一个线程修改了一个被volatile修饰共享变量的值,新值总是可以被其他线程立即得知
    2)禁止指令重排序优化。在执行程序时为了提高性能,编译器和处理器通常会重新安排指令的执行顺序。
     
    public class T {
    
        /*volatile*/ boolean running=true;
    
        void m(){
            System.out.println("m start");
            while (running){}
            System.out.println("m end");
        }
    
        public static void main(String[] args) {
            T t=new T();
    
            new Thread(()->t.m(),"t1").start();
    
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            t.running=false;
        }
    }

    这段代码中没加volatile的话,循环的后面的输出语句"m end"不会输出,但是main方法里面确实是已经将running的值改成了false。这里有关java的内存模型,简单来说就是程序运行时,running的值已经被加载到了缓存里面,而改的是t对象的running值在堆内存中。加了volatile就不一样了,它改完数值之后,会通知其他线程,让其他线程重新读一下堆内存中的值,也就是内存可见性。

    public class T1 {
    
        volatile int count=0;
    
        /*synchronized*/ void m(){
            for (int i=0;i<10000;i++){
                count++;
            }
        }
    
        public static void main(String[] args) {
    
            T1 t=new T1();
            List<Thread> threads=new ArrayList<Thread>();
    
            for(int i=0;i<10;i++){
                threads.add(new Thread(()->t.m(),"thread-"+i));
            }
            threads.forEach((o)->o.start());
            threads.forEach((o)->{
                try {
                    o.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            System.out.println(t.count);
        }
    }

    这段代码中,十个线程执行count++加到1w循环,理想状态当然是加到10w,但是volatile只能保持线程的可见性,不能保持原子性。给count变量加上了volatile,最后输出的count值也达不到10w。这就是volatile与synchronized的区别,volatile只能保持可见性,而synchronized可以保持可见性和原子性。但是volatile更加轻量级,能用volatile的情况下,尽量别用synchronized。

  • 相关阅读:
    6位密码框js
    总结 清除浮动的四种常见方法
    JS中关于clientWidth offsetWidth scrollWidth 的区别及意义
    字符超过长度将以省略号显示
    如何改变在浏览器上选中字体的颜色
    dev gridcontrol把event事件转换成命令
    gridcontrol datatemplate trigger
    oracle数据库一些用户管理语句
    dev gridcontrol 绑定int型及日期型的列默认当值为0时显示空白及格式化日期显示方式
    c#计算datatable中某一列值的和
  • 原文地址:https://www.cnblogs.com/ruiyeclub/p/12296259.html
Copyright © 2011-2022 走看看