Что такое атомарный?

#java #terminology #atomic

Вопрос:

Это две атомарные операции:

 int value = 5;
Object obj = new Object();
 

Но при использовании примитива в качестве параметра метода это будет рассматриваться как атомарная операция:

public void setValue(int val, Object obj){
this.value = val; // Atomic?
this.obj = obj; // Not atomic?
}

? Копия ссылки на объект не является атомарной, поскольку она включает в себя чтение и запись, верно?

Было бы правильно сказать, что единственный способ выполнить атомарную операцию над ссылкой на объект-объявить ее нулевой или назначить ей новый объект, например:

 Object obj = null;
 

и

 Object obj = new Object();
 

?

Ответ №1:

Если бы параметр в приведенном выше методе был ссылкой на объект, то операция не была бы атомарной, верно?

В целом это правильно. Хорошее эмпирическое правило состоит в том, чтобы учитывать, что атомарности вообще нет, даже с такими примитивами, как:

 int b,c; 
int a =   b - c;
 

только примитивы, но все задание потенциально не атомарно.

Если вам нужны безопасные атомарные операции, у вас есть разные возможности:

  • синхронизированные блоки
  • неизменяемые объекты
  • конкретные библиотеки (java.util.concurrent.atomic)

Комментарии:

1. Спасибо за ваш ответ! Я также отредактировал свой вопрос, так что теперь он включает пример кода при использовании ссылки на объект в вызове метода.

Ответ №2:

Когда поток считывает значение примитива (кроме long и double) или ссылки на объект, он видит значение, заданное им в этой переменной, или значение, заданное другим потоком в этой переменной.

Однако, хотя присвоение значения общей переменной в одном потоке является атомарным, это не означает, что все остальные потоки увидят новое значение сразу после этого. Для этого переменная должна быть объявлена изменчивой. volatile также делает записи в длинные и двойные атомарные. Однако в этом случае я предпочитаю использовать AtomicXXX (AtomicLong, AtomicBoolean и т. Д.).

И если вы хотите атомарно изменить значения двух общих переменных, то вам следует синхронизировать каждый доступ (чтение и запись) к этим переменным с помощью уникальной блокировки.

Более того, каждая операция «проверка, затем действие» или «чтение, затем запись» не является атомной. Это означает, что эти операции также нуждаются в синхронизации:

 a  ; // read a, increment value, write value to a
if (a > 0) {a = b;} // check value of a, then assign new value to a.
 

Каждая отдельная операция в вашем вопросе является атомной. Но внутри setValue() у вас есть две атомарные операции. Весь setValue вызов не является атомарным.

Комментарии:

1. Спасибо, что упомянули об отношениях «Бывает и раньше».

Ответ №3:

В JLS!

Когда поток использует значение переменной, получаемое им значение фактически является значением, сохраненным в переменной этим потоком или каким-либо другим потоком. Это верно, даже если программа не содержит кода для правильной синхронизации. Например, если два потока хранят ссылки на разные объекты в одном и том же ссылочном значении, переменная впоследствии будет содержать ссылку на тот или иной объект, а не ссылку на какой-либо другой объект или поврежденное ссылочное значение.

Таким образом, задание является атомарным.

Ответ №4:

 public synchronized void setValue(int val, Object obj)
 

теперь вся функция является «атомарной», термин которой я не видел в Java