Какие операции в Java считаются атомарными?

Какие операции в Java считаются атомарными?


person robinmag    schedule 21.01.2011    source источник


Ответы (3)


  • все присваивания примитивных типов, кроме long и double
  • все присвоения ссылок
  • все присвоения изменчивых переменных
  • все операции классов java.concurrent.Atomic *

а может еще что-то. Посмотрите на jls.

Как отмечено в комментариях, атомарность не подразумевает видимости. Таким образом, хотя другой поток гарантированно не увидит частично написанное int, он может никогда не увидеть новое значение.

Операции с long и double выполняются также на обычных 64-битных процессорах атомарных, хотя гарантии нет. См. Также этот запрос функции.

person maaartinus    schedule 21.01.2011
comment
Кроме того, имейте в виду, что хотя операции являются атомарными, видимость этих операций может не быть гарантирована в многопоточном приложении, если не будут приняты особые меры (подробности здесь способ для запутанного описания в комментарии ..) - person nos; 21.01.2011
comment
64 bit jvm, long and double assignments are also atomic. Вы уверены? Я бы сказал, что они предназначены для скомпилированного кода, но как насчет интерпретируемого кода? Наверное, ты прав, но есть ли гарантия? - person maaartinus; 21.01.2011
comment
Спецификация по-прежнему не требует, чтобы 64-битные JVM обеспечивали атомарность для длинных и двойных назначений. java.sun.com/docs/books/jls/ third_edition / html / memory.html # 17.7 Как известно, такое поведение зависит от реализации. Однако, скорее всего, 64-битные виртуальные машины будут реализовывать это как атомарную операцию. - person sjlee; 21.01.2011
comment
Вы уверены, что присвоения ссылок являются атомарными? Если да, то почему существует класс AtomicReference? download.oracle.com/ javase / 1.5.0 / docs / api / java / util / concurrent / - person rfeak; 30.01.2011
comment
IMHO, обычные ссылочные присвоения являются атомарными, но AtomicReference предлагает больше: compareAndSet и getAndSet, чего вы не смогли бы достичь без синхронизации. - person maaartinus; 31.01.2011
comment
@maaartinus, я поддержал ваш ответ. Спасибо! Я не был уверен во всех присваиваниях примитивных типов, кроме long и double - person Maksim Dmitriev; 21.02.2013
comment
Для модели памяти языка программирования Java одна запись в энергонезависимое длинное или двойное значение рассматривается как две отдельные записи: по одной в каждую 32-битную половину. Это может привести к ситуации, когда поток видит первые 32 бита 64-битного значения при одной записи, а вторые 32 бита - при другой записи. Запись и чтение изменчивых длинных и двойных значений всегда атомарны. Запись и чтение ссылок всегда являются атомарными, независимо от того, реализованы ли они как 32-битные или 64-битные значения docs.oracle.com/javase/specs/jls/se7/jls7.pdf - person Sergii Shevchyk; 10.04.2013
comment
Мне было бы интересно: * = / =% = + = - = & = и | = здесь описаны. - person peterk; 18.06.2013
comment
@peterk: В этом нет смысла ... атомарность связана с доступом к памяти. Когда вы пишете a *= b + c, все зависит от того, откуда берутся операнды. Используя локальные переменные, вы можете свести все это к присваиваниям и вычислениям с локальными переменными. Первое было рассмотрено выше, второе является атомарным, поскольку не имеет дело с памятью. - person maaartinus; 19.06.2013
comment
Да, похоже, теперь есть низкие накладные расходы на атомарный способ, чтобы сделать вышеупомянутое, кроме использования AtomicInteger (весь объект плюс поля) и выполнения некоторого реального fenagleing - person peterk; 20.06.2013
comment
@peterk Да, единственная альтернатива - использовать Unsafe, что довольно небезопасно и непереносимо. Есть предложение стандартизировать такие операции. - person maaartinus; 06.02.2015

В Java чтение и запись 32-битных или меньших величин гарантированно являются атомарными.
Под атомарными мы подразумеваем, что каждое действие выполняется за один шаг и не может быть прервано. Таким образом, когда у нас есть многопоточные приложения, операции чтения и записи являются потокобезопасными, и их не нужно синхронизировать.

Например, следующий код является потокобезопасным:

public class ThreadSafe   
  {  
    private int x;  
    public void setX(int x)  
          {
           this.x = x;
           } 
  }
person Saurabh Gokhale    schedule 30.01.2011
comment
..threadsafe в том смысле, что значение всегда будет либо исходным, либо заданным. Самое актуальное значение по-прежнему обязательно не отображается для других потоков из-за отсутствия изменчивого или синхронизированного. - person Mikko Wilkman; 01.02.2011
comment
+1 к тому, что говорит @MikkoWilkman. Этот фрагмент кода не следует использовать, поскольку он определенно небезопасен для потоков с точки зрения видимости памяти. - person Knuckles the Echidna; 18.05.2016

Казалось бы, казалось, что присвоение long является атомарным, на основе этого метода в AtomicLong.java:

public final void set(long newValue) {
    value = newValue;
}

Обратите внимание на отсутствие какой-либо синхронизации.

person Lyle Z    schedule 18.10.2013
comment
Посмотрите на объявление value. Это volatile. - person maaartinus; 18.10.2013
comment
То, что value равно volatile, не делает присвоение value атомарным, это просто позволяет избежать проблем с публикацией. - person Lyle Z; 05.11.2013
comment
Он делает и то, и другое, см. JLS, раздел 17.7: запись и чтение изменчивых длинных и двойных значений всегда атомарны. - person maaartinus; 06.11.2013
comment
@LyleZ, на мой взгляд, самый ценный комментарий в этой ветке. - person stdout; 24.04.2016