У меня есть глобальная переменная
volatile i = 0;
и два потока.Каждый делает следующее:
i++;
System.out.print(i);
Я получаю следующие комбинации.12, 21 и 22.
Я понимаю, почему я не получаю 11 (volatile запрещает кэширование i) и Я также понимаю 12 и 22.
ЧтоЯ не понимаю, как можно получить 21?
Единственный возможный способ, которым вы можете получить эту комбинацию, состоит в том, что печатаемая позже нить должна была быть первой, чтобы увеличить i
с 0 до1, а затем кэшируется i==1
.Затем другой поток увеличил i
с 1 до 2, а затем напечатал 2. Затем первый поток печатает кэшированный i==1
.Но я подумал, что volatile
запрещает кэширование.
Редактировать: После выполнения кода 10000 раз я получил 11 раз.Добавление volatile
к i
не меняет возможных комбинаций вообще.
пробел является правильным: volatile запрещает кэширование i
, но i++
не является атомарным.Это означает, что i
все еще получает своего рода "кэшированные" в регистре во время приращения.
r1 = i
//if i changes here r1 does not change
r1 = r1 + 1
i = r1
Это причина, почему 11 все еще возможно.21 вызван тем, что PrintStreams не синхронизированы (см. Ответ Кароля Доубеки)