AtomicInteger lazySet против набора

в чем разница между lazySet и set способы AtomicInteger? The документация не имеет много сказать о lazySet:

в конечном итоге устанавливает заданное значение.

похоже, что сохраненное значение не будет сразу установлено на желаемое значение, но вместо этого будет запланировано установить некоторое время в будущем. Но каково практическое применение этого метода? Любой пример?

6 ответов


цитирую прямо из "JDK-6275329: добавление методов lazySet в атомарные классы":

как, вероятно, последнее небольшое продолжение JSR166 для Mustang, мы добавили метод "lazySet" в атомарные классы (AtomicInteger, AtomicReference и т. д.). Это ниша метод иногда полезен при точной настройке кода неблокирующие структуры данных. Семантика что запись гарантированно не будет переупорядочена с любым предыдущая запись, но может быть переупорядочен с последующими операциями (или, что эквивалентно, может быть не видно другим потокам) до происходит какое-то другое действие записи или синхронизации volatile).

основной вариант использования-для обнуления полей узлов в неблокирующие структуры данных исключительно во избежание долгосрочное удерживание отброса; оно применяется когда безвредно если другие потоки некоторое время видят ненулевые значения, но вы как гарантировать, что структуры, в конечном счете, GCable. В таких случаи, вы можете получить лучшее представление путем избегать стоимость нулевой волатильной записи. Есть несколько другие варианты использования по этим направлениям для не связанных с ссылками Атомикс, поэтому метод поддерживается во всех Классы AtomicX.

для людей, которые любят думать об этих операций с точки зрения барьеры машинного уровня на общих мультипроцессорах, lazySet обеспечивает предшествующий барьер магазин-магазин (который либо нет или очень дешево на текущих платформах), но нет барьер магазин-нагрузки (который обычно дорогая часть Летучего-пишите).


В могут быть использованы для урмм Интер-нить общения, потому что обмена является атомарным, а для видимости, когда писатель-нить процесс изменения кэша строке location, читатель потока процессор увидите его на следующей читать, потому что кэш согласованности протоколов процессор Intel гарантируют в строительство, но кэш строки будут обновлены на следующей, опять же, процессор должен быть достаточно современным.

http://sc.tamu.edu/systems/eos/nehalem.pdf Для Нехалема, который является многопроцессорная платформа, процессоры имеют возможность "вынюхивать" (подслушивать) адресную шину для доступа других процессоров к системной памяти и к их внутренним кэшам. Они используют эту возможность отслеживания, чтобы их внутренние кэши согласовывались как с системной памятью, так и с кэшами в других взаимосвязанных процессорах. Если с помощью snooping один процессор обнаруживает, что другой процессор намерен записать в ячейку памяти, которая в настоящее время кэшируется в общем состоянии, процессор snooping сделает недействительным его блок кэша, заставляя его выполнять заполнение строки кэша при следующем доступе к тому же местоположению памяти.

oracle hotspot jdk для архитектуры процессора x86->

lazySet = = небезопасно.putOrderedLong == xchg rw (инструкция asm, которая служит мягким барьером стоимостью 20 циклов на процессоре nehelem intel)

на x86 (x86_64) такой барьер намного дешевле по производительности, чем volatile или AtomicLong getAndAdd,

в одном продюсере, один сценарий потребительской очереди, xchg soft barrier может заставить строку кодов перед lazySet (sequence+1) для потока производителя произойти до любого кода потока потребителя, который будет потреблять (работать) новые данные, конечно, поток потребителя должен будет атомарно проверить, что последовательность производителя была увеличена ровно на один, используя compareAndSet (sequence, sequence + 1).

Я проследил после исходного кода Hotspot, чтобы найти точное отображение lazySet в cpp код: http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/prims/unsafe.cpp Unsafe_setOrderedLong - > SET_FIELD_VOLATILE определение - > OrderAccess: release_store_fence. Для x86_64 OrderAccess: release_store_fence определяется как использование инструкции xchg.

вы можете увидеть, как это точно определено в jdk7 (дуг Леа работает над некоторыми новыми вещами для JDK Восемь): http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/4fc084dac61e/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp

вы также можете использовать hdis для разборки сборки кода lazySet в действии.

возникает другой вопрос: нам нужно mfence при использовании xchg


более широкое обсуждение происхождения и полезности lazySet и лежащего в основе putOrdered можно найти здесь: http://psy-lob-saw.blogspot.co.uk/2012/12/atomiclazyset-is-performance-win-for.html

подводя итог: lazySet-слабая Летучая запись в том смысле, что она действует как магазин-магазин, а не забор для загрузки магазина. Это сводится к тому, что lazySet скомпилирован в инструкцию MOV, которая не может быть переупорядочена компилятором, а затем значительно больше дорогостоящая инструкция, используемая для набора volatile.

при чтении значения вы всегда в конечном итоге делаете летучее чтение(с атомарным*.GET() в любом случае).

lazySet предлагает одному писателю последовательный изменчивый механизм записи, т. е. для одного писателя совершенно законно использовать lazySet для увеличения счетчика, несколько потоков, увеличивающих один и тот же счетчик, должны будут разрешить конкурирующие записи с помощью CAS, что именно и происходит под обложками Atomic* для incAndGet.


с Concurrent-atomic package summary

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

Если вам интересно о lazySet, то вы должны себе другие объяснения тоже

эффекты памяти для доступа и обновления atomics в целом следуйте правилам для летучих веществ, как указано в разделе 17.4 Java™ спецификации языка.

get имеет эффекты памяти значение переменной volatile.

set имеет эффекты памяти записи (назначения) volatile переменная.

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

weakCompareAndSet атомарно считывает и условно записывает переменную, но не создает никаких событий-перед заказами, поэтому обеспечивает отсутствие гарантий в отношении предыдущего или последующего чтения и записи любых переменных кроме цели weakCompareAndSet. compareAndSet и все другие операции чтения и обновления, такие как getAndIncrement имеют эффекты памяти чтения и записи volatile-переменных.


вот это мое понимание, поправьте меня, если я ошибаюсь: Вы можете думать о!--0--> Как" полу " volatile: это в основном энергонезависимая переменная с точки зрения чтения другими потоками, т. е. значение, заданное lazySet, может не отображаться для других потоков. Но он становится изменчивым, когда происходит другая операция записи (может быть из других потоков). Единственное влияние lazySet я могу себе представить compareAndSet. Поэтому, если вы используете lazySet(), get() из других потоков все еще может получить старое значение, но compareAndSet() всегда будет иметь новое значение, так как это операция записи.


Re: попытка заглушить его -

вы можете думать об этом как о способе обработки Летучего поля, как если бы оно не было летучим для определенного хранилища (например: ref = null;).

Это не совсем точно, но этого должно быть достаточно, чтобы вы могли принять решение между "хорошо, мне действительно все равно" и "хм, дайте мне подумать об этом немного".