关键字: volatile

参考原文: http://www.importnew.com/18126.html
基本是对原文的精简, 推荐阅读原文以获得详细讲解.

volatile能够保证值在修改时会立即更新到主存. 当其他线程读取时读到的一定是最新的

volatile关键字和java内存模型有关, 所以先了解下内存模型

简述:
cpu运行速度远快于对内存的读写, 为了加快速度, 增加了高速缓存. 而一旦增加缓存, 就会出现缓存一致性问题.

解决思路:
1. 在总线上加Lock;
2. 通过缓存一致性协议;

早期使用思路1解决问题, 但是这样的话其他cpu无法访问内存, 效率低下.
所以出现了缓存一致性协议, 最出名的就是Intel的MESI协议.

核心思路:
当cpu写数据的时候, 如果发现操作的变量是共享变量, 即在其他cpu中也存在该变量的副本, 则发出信号通知其他cpu将该变量的缓存行置为无效状态. 让他们重新从内存中读取最新值.

并发编程常见问题:
1.原子性问题;
2. 可见性问题; 一个线程修改了变量, 其他线程能够立马看到修改的值.
3. 有序性问题;

有序性

虚拟机--指令重排序

//好例子
//线程1:
context = loadContext();   //语句1
inited = true;             //语句2
 
//线程2:
while(!inited ){
  sleep()
}
doSomethingwithconfig(context);

语句1和语句2可能被重排, 导致线程2读取inited为true. 结果加载配置的时候却没加载到....

指令重排序不会影响单线程的执行, 但是会影响线程并发执行的正确性.

java内存模型

java内存模型规定所有的变量都存在主存当中, 每个线程有自己的工作内存, 线程对变量的操作都必须在工作内存中进行, 而不能直接对主存进行操作, 并且每个线程不能访问其他线程的工作内存.

x = 10;         //语句1   **原子性**
y = x;         //语句2     **不是原子性**  包含两个动作: 1.读取x的值;  2.写入工作内存;(注意工作内存四个字)
x++;           //语句3      **不是原子性**  三步: 读-改-写  
x = x + 1;     //语句4     **不是原子性**  三步: 读-改-写  

在32位平台上, 保存64位数据会分成两节. 导致不能保证原子性(现在据说已经实现原子性了?)...但是不论如何, 加上volatile关键字是良好的编程规范.

synchronized和lock自然也能保证可见性. 只是性能上没有volatile更优. 请因地制宜, 合理使用.

volatile的两层含义

  1. 保证了不同线程对这个变量操作时的可见性;
  2. 禁止进行指令重排序;

"禁止指令重排序"的实际使用

//线程1:
context = loadContext();   //语句1
volatile inited = true;             //语句2    加上volatile,保证语句2在语句1之后执行.
 
//线程2:
while(!inited ){
  sleep()
}

doSomethingwithconfig(context);

volatile保证可见性, 却无法保证原子性.

使用volatile关键字的两个条件:

  1. 对变量的写操作不依赖于当前值;
  2. 该变量没有包含在具有其他变量的不变式中;

下面列举几个Java中使用volatile的几个场景。

1.状态标记量

volatile boolean flag = false;
while(!flag){
    doSomething();
}
public void setFlag() {
    flag = true;
}
volatile boolean inited = false;
//线程1:
context = loadContext();  
inited = true;            
 
//线程2:
while(!inited ){
sleep()
}
doSomethingwithconfig(context);

2.double check

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)