zoukankan      html  css  js  c++  java
  • java基础---多线程---volatile详解

    ===volatile作用?volatile的实现原理是什么呢?lock前缀的效果是什么呢?
    volatile的作用:
    1.可见性。一个线程对volatile变量进行写操作之后,其他线程都能够看到。
    2.原子性。单个volatile变量的读写具有原子性,但是复合操作不满足原子性。
    用来修饰变量
    对volatile修饰的变量进行修改操作的时候,会在操作指令之前添加上LOCK前缀。
    LOCK前缀的效果是:命名    
    1.当前处理器缓存行的数据会写回到系统内存的时候会先获取总线,同时其他cpu阻塞。
    2.保证缓存一致性,会使得其他CPU缓存的数据失效。因为其他cpu会不断嗅探总线,一发现自己缓存的数据被修改了就做失效标记。被标记之后要用的时候会重新从系统内存拿。
    缓存一致性可能存在的问题:大量缓存一致性流量
    volatile本身的内存语义
    线程写volatile变量相当于给接下来要读取这个变量的线程发送消息。
    线程读volatile变量相当于接收之前某个线程发出的消息。
    两种都要经过主内存这个中间桥梁。
    volatile读写防止指令重排序
    能够建立一个内存屏障,一定程度上禁止指令重排序。重排序的时候不会把前面的读写指令重排序影响到volatile写,同时也不会把后面的指令放在内存屏障前面。同时保证在执行到内存屏障这条指令的时候,前面的操作都是已经完成的。
     
    CPU是如何保证原子性的?
    1.加总线锁。通过Lock#指令锁住总线,防止其他处理器同时修改内存。
    2.加缓存锁定。通过缓存一致性让其他cpu的缓存数据失效。
    java中如何实现原子性
    1.使用CAS
    2.使用重量级锁,但是这种锁的获取和释放还是使用CAS,因为是需要进入队列的。重量级锁也有同步队列。
     
     
    volatile在单例模式中的应用
    private valitle static Instance instance;
    public static Instance getInstance(){
        if (instance == null){
            synchronized(Instance.class){
                if (instance == null) {
                    instance = new Instance(); //首先这步骤是复合操作
                }
            }
        }
        return instance;
    }
    如果第一个线程进来执行到初始化这步了:
    因为中间实例化的步骤是一个复合操作,相当于三个步骤
    1.分配内存空间
    2.初始化
    3.引用指向
    但是由于单线程情况下会出现指令重排序,23颠倒了,所以引用先指向了那个还没初始化的内存空间。
    这个时候另一个线程进来能够看到instance非空那么就直接返回了,但是其实还没有初始化完成,所以出错。
     
    使用volatile修饰instance就是为了防止指令冲排序,因为最后一步引用指向相当于一个volatile写操作,通过内存屏障就能够防止指令重排序了。
     
     
     
     
     
  • 相关阅读:
    Virtualbox-CentOS网络配置
    使用phpmyadmin创建数据库
    Vue CLI的使用
    webpack3的使用
    Vue组件化之插槽
    Vue组件化开发
    Vue高级技巧
    Vue基础学习笔记
    Git解决冲突和diff用法
    Git常用命令举例
  • 原文地址:https://www.cnblogs.com/buptyuhanwen/p/9546603.html
Copyright © 2011-2022 走看看