Я пытаюсь запустить несколько потоков. Я ясно получаю состояние гонки и в состоянии решить ее следующим образом:Состояние гонки даже после синхронизации
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();
}
Но я не хочу, чтобы синхронизировать на этом блоке, и вместо этого хотите, чтобы справиться с этим в классе данных. Поэтому я удалил вышеупомянутый блок синхронизации и вместо этого синхронизировал методы get и set в классе Data следующим образом, но это все еще вызывает условия гонки. Почему проблема, хотя я их синхронизировал?
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