акузьминых уже объяснил почему if (x < y)
может быть правдой. Вы также спросили, почему вы никогда не видите того же явления, когда выполняете if (y > x)
.
Причина в том, что в java выражения всегда оцениваются слева направо, а когда вы делаете y > x
, y
всегда будет загружаться из памяти первым, поэтому x
уже был увеличен до y
, и если x
будет считываться с последующей итерации, он также будет больше y
.
Вы все еще можете видеть, что «DataRace обнаружен» печатается, когда вы делаете y > x
, но это может произойти тогда и только тогда, когда x
близко к Integer.MAX_VALUE
, и оно переполняется и становится отрицательным в последующих итерациях после того, как y
было прочитано из память и только потом x
читается из памяти.
public class Check {
public static void main(String[] args) {
DataRace dr = new DataRace();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 100_000; i++) {
dr.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 100_000; i++) {
dr.check();
}
});
t1.start();
t2.start();
}
private static class DataRace {
private volatile int x,y;
public void increment() {
// to make sure the race condition is caused by the ++ and not by the assignment
synchronized (this) {
x = Integer.MAX_VALUE;
y = Integer.MAX_VALUE;
}
x++;
y++;
}
public synchronized void check() {
if (y > x) {
System.out.println("DataRace detected: y > x");
}
}
}
}