Этот вопрос вдохновлен
Возьмите этот JVM
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
и следующий код
public class Driver implements Runnable {
public static void main(String args[]) throws Exception {
Driver driver = new Driver();
Thread thread = new Thread(driver);
thread.start();
Thread.sleep(100); // make sure threads are unsynced
driver.stop = true;
}
boolean stop = false; // not volatile
@Override
public void run() {
// Loop until stop is set to true.
while (!stop) {
doSomething(stop);
// System.out.println("random string");
}
System.out.println("done");
}
public static void doSomething(boolean value) {
/*ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
out.write(new byte[] {1});
} catch (IOException e) {
e.printStackTrace();
}*/
}
}
Когда я запускаю код, поток thread
никогда не видит значение stop
как true
и поэтому никогда не выходит из цикла while
(он может в конечном итоге, но в краткосрочной перспективе он не).
Обратите внимание на использование stop
в этом вызове
doSomething(stop);
В байтовом коде это эквивалентно его использованию в цикле while
, т.е. есть инструкция байтового кода
11: getfield #14 // Field stop:Z
Поэтому я не понимаю, почему это должно иметь какой-то эффект.
Теперь, если вы раскомментируете один из
// System.out.println("random string");
или код внутри doSomething(boolean)
, тогда код выполняет около 100 мс (время Thread.sleep()
), а затем заканчивается естественно, т.е. значение stop
синхронизируется.
Ничто из того, что я знаю, не объясняет этого поведения. Похоже, использование OutputStream
влияет на то, как и когда поток обновляет его представление о значении поля. Возможно ли это или я чего-то не хватает?
Что может заставить обновить представление потока значения энергонезависимой переменной?