zoukankan      html  css  js  c++  java
  • volatile

    一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

    内存可见性:即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的

    内存屏障(memory barrier):如果你的字段是volatile,Java内存模型将在写操作后插入一个写屏障指令,在读操作前插入一个读屏障指令。这意味着如果你对一个volatile字段进行写操作,你必须知道:1、一旦你完成写入,任何访问这个字段的线程将会得到最新的值。2、在你写入前,会保证所有之前发生的事已经发生,并且任何更新过的数据值也是可见的,因为内存屏障会把之前的写入值都刷新到缓存

     例如你让一个volatile的integer自增(i++),其实要分成3步:1)读取volatile变量值到local; 2)增加变量的值;3)把local的值写回,让其它的线程可见。这3步的jvm指令为

    mov    0xc(%r10),%r8d ; Load
    inc    %r8d           ; Increment
    mov    %r8d,0xc(%r10) ; Store
    lock addl $0x0,(%rsp) ; StoreLoad Barrier

       注意最后一步是内存屏障,写屏障指令

    内存可见性

    /**
     * volatile可以保证属性的可见性,一个线程修改了,另一个线程可以立刻知道该线程被修改了
     *
     */
    public class VolatileTest {
    
        private static volatile  int INIT_VALUE = 0;
    
        private final static int MAX_LIMIT = 5;
    
        public static void main(String[] args) {
            new Thread(() -> {
                int localValue = INIT_VALUE;
                while (INIT_VALUE < MAX_LIMIT) {
                    System.out.printf("Update the value to [%d]
    ", ++localValue);
                    INIT_VALUE = localValue;
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "UPDATER").start();
            
            new Thread(() -> {
                while (INIT_VALUE <  3) {
                    
                }
                System.out.println("结束循环了");
            }, "READER").start();
    
        }
    }

    内存屏障,防止重排序

    class Singleton {
        private volatile static Singleton instance = null;
         
        private Singleton() {
             
        }
         
        public static Singleton getInstance() {
            if(instance==null) {
                synchronized (Singleton.class) {
                    if(instance==null)
                        instance = new Singleton();
                }
            }
            return instance;
        }
    }

    volatile不具备原子性

    public class VolatileTest {
        
        private static volatile long value = 0;
    
        public static void main(String[] args) throws InterruptedException {
    
            Thread t1 = new Thread(new LoopVolatile());
            t1.start();
    
            Thread t2 = new Thread(new LoopVolatile2());
            t2.start();
    
            t1.join();
            t2.join();
            System.out.println("final val is: " + value);  // final val is: 18585
        }
    
        private static class LoopVolatile implements Runnable {
            public void run() {
                long val = 0;
                while (val < 10000L) {
                    value++;
                    val++;
                }
            }
        }
    
        private static class LoopVolatile2 implements Runnable {
            public void run() {
                long val = 0;
                while (val < 10000L) {
                    value++;
                    val++;
                }
            }
        }
    }

    CPU高速缓存

    JMM  java内存模型

  • 相关阅读:
    如何使 Postgresql 的psql 使用 中文提示信息
    Makfile中的 依赖关系
    防范计算机木马入侵反恶意联盟落户滨海 狼人:
    印度最大软件开发商塔塔咨询官网首页被黑 狼人:
    河北银行:用CDP保障业务系统的故障快速恢复 狼人:
    甲骨文11g数据库爆零日攻击 可完全攻破 狼人:
    Adobe Reader与IE 领衔漏洞榜 狼人:
    黑客藏毒于火狐插件 目标瞄准Windows系统 狼人:
    网络订票当心三类陷阱 最好当场识别真伪 狼人:
    微软基于云计算免费杀毒软件Morro曝光 狼人:
  • 原文地址:https://www.cnblogs.com/moris5013/p/10706547.html
Copyright © 2011-2022 走看看