Атомарные и неатомарные операции (java)

769
19 января 2017, 03:12

Как понять, какие операции являются атомарными, а какие неатомарными?

Вот что я нашла на Хабре:

Операция в общей области памяти называется атомарной, если она завершается в один шаг относительно других потоков, имеющих доступ к этой памяти. Во время выполнения такой операции над переменной, ни один поток не может наблюдать изменение наполовину завершенным. Атомарная загрузка гарантирует, что переменная будет загружена целиком в один момент времени. Неатомарные операции не дают такой гарантии.

Т.е. как я поняла, атомарные операции - это достаточно мелкие, выполняющиеся "за один шаг относительно других потоков". Но что значит этот "шаг"?

Один шаг == одной машинной операции? Или чему-то другому? Как определить точно, какие операции относятся к атомарным, а какие к неатомарным?

P.S.: Я нашла похожий вопрос, но там речь идёт о C#...

Answer 1

Попробую объяснить. Могу ошибаться.

Есть java, исходники компилируются в байткод. Байткод во время выполнения программы преобразуется в машинный код. Одна инструкция/команда в байткоде может преобразоваться в несколько инструкций машинного кода. В этом и заключается проблема атомарности. Процессор не может за раз выполнить одну команду, написанную на языке высокого уровня: он выполняет машинный код, содержащий последовательность команд. Следовательно, если разные процессоры выполняют манипуляции над одними и теми же данными, то различные инструкции процессоров могут чередоваться.

Приведу пример:

Есть глобальная переменная:

public volatile int value = 0;
first-thread {
    value++
}
second-thread{
    value++ 
}

Инкрементирование переменной не является атомарной операцией: оно требует, как минимум, три инструкции:

  • прочитать данные
  • увеличить на единицу
  • записать данные

Соответственно, два потока должны выполнить эту последовательность, но порядок их выполнения между ними не определен, и могут возникнуть ситуации вроде этой:

  1. Первый поток прочел данные
  2. Второй поток прочел данные
  3. Первый поток увеличил значение на 1
  4. Второй поток увеличил значение на 1
  5. Второй поток записал значение
  6. Первый поток записал значение

В результате имеем результат 1, а не 2 как ожидалось.

Чтобы такого не происходило, используют либо синхронизацию, либо атомарные примитивы из пакета java.util.concurrent

READ ALSO
“Не удалось открыть веб-страницу” WebView

“Не удалось открыть веб-страницу” WebView

Здравствуйте, такая проблема: Если отсутствует соединение с интернетом - пытаюсь брать страницу из кэша(код ниже)

414
Spring приложение и tomcat

Spring приложение и tomcat

Допустим я собрал jar по туториалу с офф сайта springio

374
Работа с кешем в WebView

Работа с кешем в WebView

WebView сохраняет в кэш страницу и по возможности не загружает её, а берёт именно оттудаЧто будет

395
Принцип работы библиотеки AndroidTreeView

Принцип работы библиотеки AndroidTreeView

Такой вопрос, необходимо построить деревоРодитель -дети

376