说说并发编程 volatile
Java volatile关键字是用来保证变量的线程可见性。到底什么是线程的可见性呢?准确地讲,每次读取volatile变量要从主内从中读取,而不是从CPU cache中读取;写一个volatile变量,要直接写到主内存,而不仅仅是CPU cache。
Java 5 引入了volatile,就保证了读写都要从主内存中取值。下边详细介绍一下:
线程可见性
在多线程应用程序中, 当线程操作非volatile变量,每个线程需要复制变量从主内存到 CPU缓存中,出于性能方面的设计。如果你的计算机包含多个 CPU,每个线程可能会在不同的 CPU 上运行。这意味着,每个线程可能会将变量复制到不同的 Cpu 的 CPU 缓存。如下所示 ︰
非volatile变量不保证从主内存中立即读取数据或将数据从CPU 缓存中直接写入到主内存。如果多线程操作一个共享变量的话,就会出现如下的问题:
[java]
public class SharedObject {
public volatile int counter = 0;
}
[/java]
想象一下,如果只有线程1更新counter变量,但是线程1和线程2却可能拿到的不是最新的值。如果没用申明volatile,JVM并不保证counter变量的值马上写回到主内存中,那就意味着CPU cache中的值并不是最新的值。如下图所示:
这就是线程可见性的问题。线程2并没有实时看到最新的值,因为JVM会先从CPU cache中读取值。
如果申明为volatile,则线程读取值,必须从主内存中读取,写值,必须写到主内存中,这就保证了所有的值对于线程是可见的。但是这不能说明它是线程安全的。这是两个不同的概念。
例子
[java]
package com.learn.core.ch02;
public class VolatileTest {
private int count = 0;
public static void main(String[] args) throws InterruptedException {
while (true) {
VolatileTest test = new VolatileTest();
test.setCount(0);
Thread[] ts = new Thread[2];
for (int i = 0; i < 2; i++) {
ts[i] = new Thread(new MyRun(test, i));
ts[i].start();
}
for (Thread t : ts) {
t.join();
}
Thread.sleep(2);
}
}
public static class MyRun implements Runnable {
private VolatileTest test;
private int index;
public MyRun(VolatileTest test2, int index) {
this.test = test2;
this.index = index;
}
@Override
public void run() {
if (index == 0) {
test.increment();
} else {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (test.getCount() == 0) {
System.out.println(Thread.currentThread().getName() + "—–" + test.getCount());
}
}
}
public int getCount() {
return count;
}
public void increment() {
count++;
}
public void setCount(int count) {
this.count = count;
}
}
[/java]
Thread-10181—–0
Thread-10957—–0
Thread-10959—–0
Thread-11643—–0
Thread-12177—–0
Thread-12269—–0
Thread-12345—–0
Thread-12929—–0
Thread-13221—–0
加上volatile关键字,就可以保证永远拿到最新的值,前提是写的线程先执行。
2 thoughts on “说说并发编程 volatile”
_∧_∧_
((∀`/ )
/⌒ /
/(__ノ\_ノ
(_ノ |||
好棒啊~~赞~~~
∧_∧ ∧_∧
(( ・∀・ ))・∀・) )
`\ ∧ ノ
/ |/ |
(_ノ_)_ノL_)
分析的不错