Изменчивая ссылка Java против AtomicReference - PullRequest
127 голосов
/ 11 ноября 2008

Есть ли разница между volatile ссылкой на объект и AtomicReference в случае, если бы я просто использовал get() и set() -методы из AtomicReference?

Ответы [ 5 ]

104 голосов
/ 11 ноября 2008

Краткий ответ: Нет.

Из пакета java.util.concurrent.atomic doc :

Эффекты памяти для обращений и обновлений атомов обычно следуют правилам для летучих:

  • get имеет эффект памяти чтения переменной volatile.
  • set имеет эффект памяти записи (присваивания) переменной volatile.

Кстати, документация на пакет очень хорошая и все объясняется ...


lazySet (введено в Java 6) - это более новая введенная операция, в которой семантика недостижима через volatile переменных; см. этот пост для получения дополнительной информации.

40 голосов
/ 11 ноября 2008

Нет, нет.

Дополнительные возможности, предоставляемые AtomicReference, - это метод compareAndSet () и друзья. Если вам не нужны эти методы, переменная ссылка предоставляет ту же семантику, что и AtomicReference.set () и .get ().

8 голосов
/ 19 июля 2017

Есть несколько отличий и компромиссов:

  1. Использование AtomicReference get / set имеет ту же семантику JMM , что и энергозависимое поле (как состояния javadoc), но AtomicReference является оболочкой для ссылки, поэтому любой доступ к полю включает дальнейшую погоню за указателем .

  2. Объем памяти умножается (при условии сжатой среды ООП, что справедливо для большинства ВМ):

    • изменчивый ref = 4b
    • AtomicReference = 4b + 16b (заголовок объекта 12b + поле ссылки 4b)
  3. AtomicReference предлагает более богатый API, чем энергозависимая ссылка. Вы можете восстановить API для энергозависимой ссылки, используя AtomicFieldUpdater или Java 9 a VarHandle. Вы также можете набрать sun.misc.Unsafe, если вам нравится бегать с ножницами. Сам AtomicReference реализован с использованием Unsafe.

Итак, когда лучше выбрать одно из другого:

  • Нужно только получить / установить? Придерживайтесь изменчивого поля, простейшего решения и минимальных накладных расходов.
  • Нужна дополнительная функциональность? Если это часть кода, чувствительная к производительности (скорости / нагрузке на память), сделайте выбор между AtomicReference / AtomicFieldUpdater / Unsafe, где вы склонны платить за удобочитаемость и риск увеличения производительности. Если это не чувствительная область, просто перейдите на AtomicReference. Авторы библиотек обычно используют сочетание этих методов в зависимости от целевых JDK, ожидаемых ограничений API, ограничений памяти и т. Д.
6 голосов
/ 03 февраля 2013

Исходный код JDK - один из лучших способов ответить на подобные ошибки. Если вы посмотрите на код в AtomicReference, он использует переменную volatie для хранения объектов.

private volatile V value;

Итак, очевидно, что если вы собираетесь просто использовать get () и set () в AtomicReference, это похоже на использование переменной volatile. Но, как прокомментировали другие читатели, AtomicReference предоставляет дополнительную семантику CAS. Итак, сначала решите, хотите ли вы семантику CAS или нет, и если вы делаете только тогда, используйте AtomicReference.

2 голосов
/ 30 января 2009

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

Однако, если вам не нужны эти дополнительные функции, я предлагаю использовать простое изменчивое поле.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...