Чутлива операція в моїй лабораторії сьогодні пішла зовсім не так. Привід на електронному мікроскопі перейшов його межу, і після ланцюжка подій я втратив обладнання в $ 12 млн. Я звузив більше ніж 40 К рядків у несправному модулі до цього:
import java.util.*;
class A {
static Point currentPos = new Point(1,2);
static class Point {
int x;
int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public static void main(String[] args) {
new Thread() {
void f(Point p) {
synchronized(this) {}
if (p.x+1 != p.y) {
System.out.println(p.x+" "+p.y);
System.exit(1);
}
}
@Override
public void run() {
while (currentPos == null);
while (true)
f(currentPos);
}
}.start();
while (true)
currentPos = new Point(currentPos.x+1, currentPos.y+1);
}
}
Деякі зразки результатів, які я отримую:
$ java A
145281 145282
$ java A
141373 141374
$ java A
49251 49252
$ java A
47007 47008
$ java A
47427 47428
$ java A
154800 154801
$ java A
34822 34823
$ java A
127271 127272
$ java A
63650 63651
Оскільки тут немає арифметики з плаваючою комою, і всі ми знаємо, що підписані цілі числа добре поводяться при переповненні Java, я думаю, що в цьому коді нічого поганого. Однак, незважаючи на вихід, який вказує на те, що програма не досягла умови виходу, вона досягла умови виходу (вона була досягнута і не досягнута?). Чому?
Я помітив, що цього не відбувається в деяких умовах. Я на OpenJDK 6 на 64-розрядному Linux.
final
класифікатора (який не впливає на створений байт-код) до полів x
та y
"вирішує" помилку. Хоча це не впливає на байт-код, поля позначені ним, що змушує мене думати, що це побічний ефект оптимізації JVM.
Point
p
, яке задовольняє p.x+1 == p.y
, після чого посилання передається на поточну дільницю. Врешті-решт опитувальний потік вирішує вийти, оскільки він вважає, що умова не задоволена для одного з отриманих Point
s, але тоді вихід консолі показує, що його слід було задовольнити. Відсутність volatile
тут просто означає, що нитка для опитування може застрягнути, але тут явно не проблема.
synchronized
помилка не відбувається? Це тому, що мені довелося випадково писати код, поки я не знайшов той, який би відтворив цю поведінку детерміновано.