いくつかのマルチスレッド Java コードで発行エラーを引き起こそうとしています。
以下のサンプルはうまくいくように見えますが、今のところ期待どおりに動作します。確かに、私はこれを MacBook Pro (2.8 GHz Intel Core i7 を搭載した OSX 10.7.4) で 2 つのコア (およびハイパースレッディング) のみで実行しています。したがって、一度に実行できるスレッドは 4 つだけです。
出版の失敗を誘発するためのより良いアイデアはありますか?
package demo;
import java.util.concurrent.CyclicBarrier;
public class UnsafePublicationTest {
private static final String FIRST_VAL = "FAIL";
private static final String SECOND_VAL = "GOOD";
public void test() throws Exception {
UnsafePublisher unsafe = new UnsafePublisher();
unsafe.setValue(FIRST_VAL);
CyclicBarrier gate = launchThreads(10, unsafe);
gate.await(); // Start all threads at once
gate.await(); // Each thread reads the first value
// Should cause errors since update is not published
unsafe.setValue(SECOND_VAL);
gate.await(); // Each thread tries for the second value
gate.await(); // Wait for the readers finish
}
private CyclicBarrier launchThreads(int count, UnsafePublisher unsafe) {
CyclicBarrier gate = new CyclicBarrier(count + 1);
for (int id = 0; id < count; id++) {
ValueReader rdr = new ValueReader(id, gate, unsafe);
rdr.start();
}
return gate;
}
private static class UnsafePublisher {
private String fValue;
public UnsafePublisher() { /* no synthetic ctor */ }
public void setValue(String value) {
this.fValue = value;
}
public String getValue() {
return fValue;
}
}
private static class ValueReader extends Thread {
private final int fId;
private final CyclicBarrier fGate;
private final UnsafePublisher fTest;
public ValueReader(int id, CyclicBarrier gate, UnsafePublisher test) {
fId = id;
fGate = gate;
fTest = test;
}
public void run() {
try {
fGate.await();
int noOp = this.hashCode();
// Try to get the thread to cache the value.
for (int i = 0; i < 10000; i ++) {
for (int j = 0; j < 10000; j++) {
String first = fTest.getValue();
noOp = noOp ^ first.hashCode();
if (!FIRST_VAL.equals(first))
System.out.println("Thread " + fId + " read " + first);
}
}
fGate.await();
// Between these awaits, the value is changed.
fGate.await();
String second = fTest.getValue();
if (!SECOND_VAL.equals(second))
System.out.println("Thread " + fId + " read " + second);
System.out.println("Thread " + fId + " hash " + noOp);
fGate.await();
} catch (Exception err) { /* ignore */ }
}
}
public static void main(String[] args) throws Exception {
UnsafePublicationTest test = new UnsafePublicationTest();
test.test();
}
}