などの複合操作i++
は複数の操作を伴うため、スレッドセーフではありません。
しかし、それ自体で参照をチェックすることはスレッドセーフな操作ですか?
a != a //is this thread-safe
私はこれをプログラムして複数のスレッドを使用しようとしましたが、失敗しませんでした。私のマシンではレースをシミュレートできなかったと思います。
編集:
public class TestThreadSafety {
private Object a = new Object();
public static void main(String[] args) {
final TestThreadSafety instance = new TestThreadSafety();
Thread testingReferenceThread = new Thread(new Runnable() {
@Override
public void run() {
long countOfIterations = 0L;
while(true){
boolean flag = instance.a != instance.a;
if(flag)
System.out.println(countOfIterations + ":" + flag);
countOfIterations++;
}
}
});
Thread updatingReferenceThread = new Thread(new Runnable() {
@Override
public void run() {
while(true){
instance.a = new Object();
}
}
});
testingReferenceThread.start();
updatingReferenceThread.start();
}
}
これは、スレッドの安全性をテストするために使用しているプログラムです。
奇妙な行動
プログラムがいくつかの反復の間に開始すると、出力フラグの値を取得します。これは!=
、同じ参照で参照チェックが失敗することを意味します。しかし、いくつかの反復の後、出力は一定値にfalse
なり、プログラムを長時間実行しても、単一のtrue
出力は生成されません。
いくつかのn(固定されていない)反復の後、出力が示唆するように、出力は定数値であるように見え、変化しません。
出力:
いくつかの反復について:
1494:true
1495:true
1496:true
19970:true
19972:true
19974:true
//after this there is not a single instance when the condition becomes true
1234:true
スマッシュしないことに注意してください)。レーステストには、より厳しい内部ループが必要です。最後に要約を印刷します(誰かが単体テストフレームワークで以下に行ったように)。