Найдите и исправьте условную гонку в следующем Java-псевдокоде: "class Counter { int c=0; void inc(){ if(c

21 Ноя в 10:47
2 +2
0
Ответы
1
Проблема: проверка-then-действие неатомарна — между `if (c < 10)` и `c++` другой поток может изменить `c`, что ведёт к условной гонке.
Короткое и корректное решение — использовать атомарные операции. Два варианта (правильно и эффективно):
1) Простая синхронизация (корректно, но при высокой нагрузке — блокировка):
// начальное c = 000, предел = 101010 class Counter {
private int c = 0;
public synchronized boolean inc() {
if (c < 10) { c++; return true; }
return false;
}
public synchronized int get() { return c; }
}
2) Неблокирующий и более производительный вариант — AtomicInteger (атомарная функция):
// начальное c = 000, предел = 101010 import java.util.concurrent.atomic.AtomicInteger;
class Counter {
private final AtomicInteger c = new AtomicInteger(0);
// возвращает true, если увеличили
public boolean inc() {
return c.updateAndGet(x -> x < 10 ? x + 1 : x) 0;
// можно проще вернуть флаг по значению до/после; см. вариант с CAS ниже
}
public int get() { return c.get(); }
}
Практичнее и яснее — CAS-цикл, возвращающий успех:
class Counter {
private final AtomicInteger c = new AtomicInteger(0);
public boolean inc() {
while (true) {
int prev = c.get();
if (prev >= 10) return false;
if (c.compareAndSet(prev, prev + 1)) return true;
}
}
public int get() { return c.get(); }
}
Почему предпочтительно AtomicInteger:
- Операции неблокирующие (лучше масштабируются при высокой конкуренции).
- Обеспечивается атомарность проверки и инкремента без внешней синхронизации.
Выбор: если конкуренция низкая и код проще — synchronized; при высокой нагрузке — CAS/AtomicInteger.
21 Ноя в 11:31
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир