privatestaticvoid fork(Runnable r) { for (int i = 0; i < 10; i++) {
sThreads[i] = newThread(r);
} // Start the threads only after the full array has been written with new threads, // because one test relies on the contents of this array to be consistent. for (int i = 0; i < 10; i++) {
sThreads[i].start();
}
}
privatestaticvoid join() { try { for (int i = 0; i < 10; i++) {
sThreads[i].join();
}
} catch (InterruptedException e) { thrownew Error("Failed join: " + e);
}
}
// Some checks on setters within different threads.
fork(new Runnable() { publicvoid run() { for (int i = 0; i < 10; i++) {
set32(m, intOffset, i);
}
}
});
join();
expectEqual32(9, m.i); // one thread's last value wins
fork(new Runnable() { publicvoid run() { for (int i = 0; i < 10; i++) {
set64(m, longOffset, (long) (100 + i));
}
}
});
join();
expectEqual64(109L, m.l); // one thread's last value wins
fork(new Runnable() { publicvoid run() { for (int i = 0; i < 10; i++) {
setObj(m, objOffset, sThreads[i]);
}
}
});
join();
expectEqualObj(sThreads[9], m.o); // one thread's last value wins
// Some checks on adders within different threads.
fork(new Runnable() { publicvoid run() { for (int i = 0; i < 10; i++) {
add32(m, intOffset, i + 1);
}
}
});
join();
expectEqual32(559, m.i); // all values accounted for
fork(new Runnable() { publicvoid run() { for (int i = 0; i < 10; i++) {
add64(m, longOffset, (long) (i + 1));
}
}
});
join();
expectEqual64(659L, m.l); // all values accounted for
// Some checks on fences within same thread. Note that memory fences within one // thread make little sense, but the assertion ensures nothing bad happens.
// Some checks on full fence within different threads. We write the non-volatile m.l after // the fork(), which means there is no happens-before relation in the Java memory model // with respect to the read in the threads. This relation is enforced by the memory fences // and the weak-set() -> get() guard. Note that the guard semantics used here are actually // too strong and already enforce total memory visibility, but this test illustrates what // should still happen if Java had a true relaxed memory guard.
final AtomicBoolean guard1 = new AtomicBoolean();
m.l = 0L;
m.l = -123456789L;
full(); while (!guard1.weakCompareAndSet(false, true)); // relaxed memory order
join();
// Some checks on release/acquire fences within different threads. We write the non-volatile // m.l after the fork(), which means there is no happens-before relation in the Java memory // model with respect to the read in the threads. This relation is enforced by the memory // fences and the weak-set() -> get() guard. Note that the guard semantics used here are // actually too strong and already enforce total memory visibility, but this test // illustrates what should still happen if Java had a true relaxed memory guard.
final AtomicBoolean guard2 = new AtomicBoolean();
m.l = 0L;
m.l = -987654321L;
store(); while (!guard2.weakCompareAndSet(false, true)); // relaxed memory order
join();
// Some checks on release/acquire fences within different threads using a test suggested by // Hans Boehm. Even this test remains with the realm of soundness checking only, since // having the threads read the same value consistently would be a valid outcome.
m.x_value = -1;
m.y_value = -1;
m.running = true;
fork(new Runnable() { publicvoid run() { while (m.running) { for (int few_times = 0; few_times < 1000; few_times++) { // Read y first, then load fence, then read x. // They should appear in order, if seen at all. int local_y = m.y_value;
load(); int local_x = m.x_value;
expectLessThanOrEqual32(local_y, local_x);
}
}
}
});
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.