複数のスレッドを実行しようとしています。私は明らかに競合状態を取得し、次のようにそれを解決することができています:同期後の競合状態
final Data data = new Data();
for (int i = 0; i < numberOfThreads; i++) {
final Thread thread = new Thread(new Runnable() {
@Override
public void run() {
//using this sync block to stop the race condition
synchronized (data){
final int value = data.getValue();
data.setValue(value + 1);
}
}
});
thread.start();
}
をしかし、私はこのブロックに同期して、代わりにデータのクラスでそれを処理する必要はありません。そこで、私は上記の同期ブロックを削除し、Dataクラスのgetメソッドとsetメソッドを次のように同期させましたが、それでも競合状態が発生します。私はそれらを同期させたのになぜ問題なのですか?個々のメソッドにを追加
public class Data {
private int value;
public synchronized int getValue(){
return this.value;
}
public synchronized void setValue(int num){
this.value = num;
}
}
複数のスレッドがgetValue()を同時に呼び出すことができ、getValue()が呼び出された回数だけインクリメントされていなくても、同じ値を書き戻すことができるためです。 – markspace
競合状態がどの程度正確に現れますか? また、スレッドセーフなインクリメントが必要な場合は、[AtomicInteger](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger)を使用してください。 html)? –
これは、ダブルチェックロック(https://en.wikipedia.org/wiki/Double-checked_locking)のバリエーションです。答えが示すとおり、取得して別々に設定しています。 – stdunbar