Два потока увеличивают счётчик, итог меньше ожидаемого
long counter = 0;
void worker() {
for (int i = 0; i < 1000000; ++i)
++counter;
}
Запускаются два потока, оба выполняют worker, затем оба присоединяются через join и печатается counter. Ожидали 2000000, получают разные значения: 1370455, 1682311, изредка ровно 2000000.
Почему так происходит?
- Потоки не успевают завершить свои циклы до печати результата, поэтому в счётчике оказывается неполная сумма
- Инкремент не атомарен: чтение, увеличение и запись перемешиваются между потоками, часть увеличений теряется
- Компилятор развернул цикл и выбросил часть итераций как избыточные, потому что результат нигде не проверяется
- Достаточно объявить counter как volatile: этот квалификатор делает операцию инкремента атомарной
