Разберите проблему гонки данных в многопоточном Java-коде: Runnable r = () -> { counter++; }; Thread t1=new Thread(r); Thread t2=new Thread(r); t1.start(); t2.start(); — почему counter может быть неконсистентен и как это исправить

16 Фев в 11:41
12 +1
0
Ответы
1
Коротко — потому что операция counter++counter++counter++ не атомарна и есть проблемы видимости между потоками.
Почему так:
- counter++counter++counter++ фактически выполняется как три шага: чтение, вычисление, запись — например, read v\text{read }vread v, compute v+1\text{compute }v+1compute v+1, write v+1\text{write }v+1write v+1. При параллельном выполнении два потока могут оба прочитать одно и то же значение (скажем, 0\,00), оба записать 1\,11 — потерянное обновление: ожидаем 2\,22, получаем 1\,11.
- Без синхронизации изменения одного потока могут быть не сразу видны другому (Java Memory Model) — даже если операции не перекрываются, чтение может вернуть «старое» значение.
Как исправить (варианты, кратко):
1) Синхронизация:
- synchronized-блок:
Runnable r = () -> {
synchronized(lock) { counter++; }
};
- или synchronized-метод. Гарантирует атомарность и видимость.
2) Atomic-классы (рекомендуется для простого инкремента):
- Использовать AtomicInteger:
AtomicInteger counter = new AtomicInteger(0);
Runnable r = () -> counter.incrementAndGet();
- Это атомарно и быстрее, чем общая синхронизация при низкой/средней нагрузке.
3) ReentrantLock:
- Если нужен явный lock/unlock или tryLock:
lock.lock();
try { counter++; } finally { lock.unlock(); }
4) LongAdder для высокой конкуренции:
- LongAdder даёт лучший масштаб при большом числе потоков:
LongAdder counter = new LongAdder();
counter.increment();
long value = counter.sum();
Что не поможет:
- volatile int counter; — сделает видимым последнее значение, но не сделает counter++counter++counter++ атомарным (проблема потерянных обновлений останется).
Дополнение: чтобы корректно прочитать итог после старта потоков, дождитесь их завершения через t1.join(); t2.join(); — иначе можете читать значение до завершения инкрементов.
16 Фев в 11:46
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир