public class Volatile implements Runnable {
// not ed as ‘volatile’, but it should be!
private  int value;
private volatile boolean missedIt;
// doesn’t need to be volatile-doesn’t change
private long creationTime; public Volatile() {
value = 10;
missedIt = false;
creationTime = System.currentTimeMillis();
} public void run() {
print("entering run()");
// each time, check to see if ‘value’ is different
while (value<20) {
// Used to break out of the loop if change to
// value is missed.

if (missedIt) {
int currValue = value;
// Simply execute a synchronized statement on an
// arbitrary object to see the effect.
Object lock = new Object();
synchronized (lock) {
//do nothing
}
int valueAfterSync = value;
print("in run() - see value=" + currValue +", but rumor has it that it changed!");
print("in run() - valueAfterSync=" + valueAfterSync);
break;
}
}
print("leaving run()");
} public void workMethod() throws InterruptedException {
print("entering workMethod()");
print("in workMethod() - about to sleep for 2 seconds");
Thread.sleep(2000);
value = 50;
print("in workMethod() - just set value=" + value);
print("in workMethod() - about to sleep for 5 seconds");
Thread.sleep(5000);
missedIt = true;
print("in workMethod() - just set missedIt=" + missedIt);
print("in workMethod() - about to sleep for 3 seconds");
Thread.sleep(3000);
print("leaving workMethod()");
} private void print(String msg) {
// This method could have been simplified by using
// functionality present in the java.text package,
// but did not take advantage of it since that package
// is not present in JDK1.0.
long interval = System.currentTimeMillis() - creationTime; String tmpStr = "   " + (interval / 1000.0) + "000";
int pos = tmpStr.indexOf(".");
String secStr = tmpStr.substring(pos - 2, pos + 4);
String nameStr = "          " +Thread.currentThread().getName();
nameStr = nameStr.substring(nameStr.length() - 8,nameStr.length());
System.out.println(secStr + "  " + nameStr + " :" + msg);
} public static void main(String[] args) {
try {
Volatile vol = new Volatile();
// slight pause to let some time elapse
Thread.sleep(100);
Thread t = new Thread(vol);
t.start();
// slight pause to allow run() to go first
Thread.sleep(100);
vol.workMethod();
} catch (InterruptedException x) {
System.err.println("one of the sleeps was interrupted");
}
}}在这个程序中成员变量没有用volatile修饰
Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。
那么这个程序的期望结果应该是:
1:  0.170 Thread-0: entering run()  
 
  2:  0.280     main: entering workMethod()  
 
  3:  0.610     main: in workMethod() - about to sleep for 2 seconds  
 
  4:  2.700     main: in workMethod() - just set value=50  
 
  5:  2.700     main: in workMethod() - about to sleep for 5 seconds  
 
  6:  7.750     main: in workMethod() - just set missedIt=true  
 
  7:  7.750     main: in workMethod() - about to sleep for 3 seconds  
 
  8:  7.750 Thread-0: in run() - see value=10, but rumor has it that it changed!  
 
  9:  7.750 Thread-0: in run() - valueAfterSync=50  
 
  10:  7.750 Thread-0: leaving run()  
 
  11: 10.710     main: leaving workMethod() 
 
但是在jdk_1.6的环境下编译运行中有没有volatile结果都是一样的,如下:
 0.093  Thread-0 :entering run()
 0.203      main :entering workMethod()
 0.203      main :in workMethod() - about to sleep for 2 seconds
 2.203  Thread-0 :leaving run()
 2.203      main :in workMethod() - just set value=50
 2.203      main :in workMethod() - about to sleep for 5 seconds
 7.203      main :in workMethod() - just set missedIt=true
 7.203      main :in workMethod() - about to sleep for 3 seconds
10.203      main :leaving workMethod()
也就是说有没有volatile修饰,value的值都是和内存中的值同步的,  为什么?
是因为JIT的原因么?

解决方案 »

  1.   

    你有几个CPU?你确信他们是并发运行线程的吗?
      

  2.   

    没有仔细看程序。
    只是发现一个问题:根据概念,用volatile的话,在不是synchronized块里面的变量,都强迫从共享内存中重读该成员变量的值。如果已经是synchronized块,那么volatile就没有作用了。
    所以LZ试试把synchronized块去掉,看看用不用volatile是否有区别了?
      

  3.   

    一个cpu ,  但是不是每个线程都维持自己一份共享成员的私有拷贝么?