【发布时间】:2012-07-02 03:19:36
【问题描述】:
我最近遇到了 volatile 关键字的这种奇怪行为。据我所知,
volatile 关键字应用于变量以反映对数据所做的更改 变量由一个线程转移到另一个线程。
volatile 关键字防止在线程上缓存数据。
我做了一个小测试............
我使用了一个名为count的整数变量,并在其上使用了volatile关键字。
然后做了2个不同的线程将变量值增加到10000,所以最终结果应该是20000。
-
但情况并非总是如此,使用 volatile 关键字我不会始终获得 20000,而是 18534、15000 等......有时甚至是 20000。
但是当我使用同步关键字时,它工作得很好,为什么....??
谁能解释一下 volatile 关键字的这种行为。
我正在发布我的带有 volatile 关键字的代码以及带有 synchronzied 关键字的代码。
以下代码在变量计数上与 volatile 关键字的行为不一致
public class SynVsVol implements Runnable{
volatile int count = 0;
public void go(){
for (int i=0 ; i<10000 ; i++){
count = count + 1;
}
}
@Override
public void run() {
go();
}
public static void main(String[] args){
SynVsVol s = new SynVsVol();
Thread t1 = new Thread(s);
Thread t2 = new Thread(s);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Total Count Value: "+s.count);
}
}
以下代码与 go() 方法中的 synchronized 关键字完美结合。
public class SynVsVol implements Runnable{
int count = 0;
public synchronized void go(){
for (int i=0 ; i<10000 ; i++){
count = count + 1;
}
}
@Override
public void run() {
go();
}
public static void main(String[] args){
SynVsVol s = new SynVsVol();
Thread t1 = new Thread(s);
Thread t2 = new Thread(s);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Total Count Value: "+s.count);
}
}
【问题讨论】:
-
想象一个线程在
count = count + 1指令期间被切换——特别是在它接收count之后和存储count + 1之前。你只需要看到这种情况发生几千次,你就完成了。使用AtomicInteger解决此问题。
标签: java multithreading volatile synchronized