오늘 실험실에서 민감한 작업이 완전히 잘못되었습니다. 전자 현미경의 액츄에이터가 그 경계를 넘어 섰고, 일련의 사건 이후 나는 1200 만 달러의 장비를 잃었습니다. 결함이있는 모듈의 40K 라인을 좁혔습니다.
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의 오버플로에서 잘 작동한다는 것을 알고 있으므로이 코드에는 아무런 문제가 없다고 생각합니다. 그러나 프로그램이 종료 조건에 도달하지 않았 음을 나타내는 출력에도 불구하고 (이것은 모두 도달 한 종료 상태에 도달 하고 도달하지?). 왜?
일부 환경에서는이 문제가 발생하지 않습니다. 64 비트 Linux 에서 OpenJDK 6을 사용하고 있습니다.
final
한정자 (생성 된 바이트 코드에 영향을 미치지 않음)를 필드에 추가 x
하고 y
버그를 "해결"합니다. 바이트 코드에는 영향을 미치지 않지만 필드에 플래그가 지정되어있어 이것이 JVM 최적화의 부작용이라고 생각하게됩니다.
Point
p
를 만족 하는 A 가 구성되면 p.x+1 == p.y
, 참조 는 폴링 스레드로 전달됩니다. 결국 폴링 스레드는 Point
수신 한 조건 중 하나에 대해 조건이 충족되지 않는다고 생각하기 때문에 종료하기로 결정 하지만 콘솔 출력은 해당 조건이 만족되어야 함을 표시합니다. volatile
여기가 없다는 것은 단순히 폴링 스레드가 멈출 수 있음을 의미하지만 여기서 분명히 문제가되지는 않습니다.
synchronized
을 제거하면 어떻게 버그가 발생하지 않습니까? 결정적인 방식으로이 동작을 재현 할 수있는 코드를 찾을 때까지 무작위로 코드를 작성해야했기 때문입니다.