#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:
Когда поток использует значение переменной, получаемое им значение фактически является значением, сохраненным в переменной этим потоком или каким-либо другим потоком. Это верно, даже если программа не содержит кода для правильной синхронизации. Например, если два потока хранят ссылки на разные объекты в одном и том же ссылочном значении, переменная впоследствии будет содержать ссылку на тот или иной объект, а не ссылку на какой-либо другой объект или поврежденное ссылочное значение.
Таким образом, задание является атомарным.
Ответ №4:
public synchronized void setValue(int val, Object obj)
теперь вся функция является «атомарной», термин которой я не видел в Java