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