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写操做,经过内存屏障就可以防止指令重排序了。
相关文章
相关标签/搜索