0. 多核CPU与缓存一致性
如果一个变量在多个CPU中都存在缓存(一般在多线程编程时才会出现),那么就可能存在缓存不一致的问题。如上图所示,为了解决缓存不一致性问题,通常来说有以下2种解决方法:
- 1)通过在总线加LOCK#锁的方式
- 2)通过缓存一致性协议
1. 并发编程要解决的三个问题
-
原子性
-
可见性
可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
举个简单的例子,看下面这段代码://线程1执行的代码 int i = 0; i = 10; //线程2执行的代码 j = i;
假若执行线程1的是CPU1,执行线程2的是CPU2。由上面的分析可知,当线程1执行 i =10这句时,会先把i的初始值加载到CPU1的高速缓存中,然后赋值为10,那么在CPU1的高速缓存当中i的值变为10了,却没有立即写入到主存当中。
此时线程2执行 j = i,它会先去主存读取i的值并加载到CPU2的缓存当中,注意此时内存当中i的值还是0,那么就会使得j的值为0,而不是10.
这就是可见性问题,线程1对变量i修改了之后,线程2没有立即看到线程1修改的值。
- 有序性
2. volatile关键字
- volatile 修饰变量等于向编译器传达如下两层含义:
- 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
- 禁止进行指令重排序。
- volatile 关键字定义了读写发生的次序:
- 对一个变量(被 volatile 修饰的变量)的写操作先行发生于(happens before)后面对这个变量的读操作
3. volatile 的应用场景
-
修饰标记量
//线程1 // boolean stop = false; ⇒ volatile boolean stop = false; while(!stop){ doSomething(); } //线程2 stop = true;
references
- <a href=“http://www.importnew.com/18126.html”, target="_blank">Java并发编程:volatile关键字解析