Это две атомарные операции:
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 · рейтинг 4 · PeterMmm
Если бы параметр в приведенном выше методе был ссылкой на объект, то операция не была бы атомарной, верно?
В целом это правильно. Хорошее эмпирическое правило состоит в том, чтобы считать, что атомарности вообще нет, даже с такими примитивами, как:
int b,c;
int a = ++b - c;
только примитивы, но все назначение является потенциальным, а не атомарным.
Если вам нужны атомарные операции, у вас есть разные возможности:
- синхронизированные блоки
- неизменяемые объекты
- определенные библиотеки (java.util.concurrent.atomic)
Ответ 2 · рейтинг 3 · JB Nizet
Когда поток читает значение примитива (кроме long и double) или ссылки на объект, он видит значение, которое он установил в этой переменной, или значение, которое другой поток установил в этой переменной.
Однако, хотя присвоение значения общей переменной в одном потоке является атомарным, это не означает, что все остальные потоки увидят новое значение сразу после этого. Для этого переменная должна быть объявлена volatile. volatile также делает записи в long и double atomic. Однако в этом случае я предпочитаю использовать 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 не является атомарным.
Ответ 3 · рейтинг 1 · Tim Bender
За JLS!
Когда поток использует значение переменной, получаемое им значение на самом деле является значением, сохраненным в переменной этим потоком или каким-либо другим потоком. Это верно даже в том случае, если программа не содержит кода для правильной синхронизации. Например, если два потока хранят ссылки на разные объекты в одном и том же значении ссылки, переменная впоследствии будет содержать ссылку на тот или иной объект, а не ссылку на какой-то другой объект или поврежденное значение ссылки.
Таким образом, задание является атомарным.
Ответ 4 · Nicholas Jordan
public synchronized void setValue(int val, Object obj)
теперь вся функция является "атомарной", термин, который я не видел в Java.