Пытаясь понять, как SubmissionPublisher( исходный код в Java SE 10, OpenJDK | docs ), новый класс, добавленный в Java SE в версии 9, был реализован, я наткнулся на несколько вызовов API, о которых VarHandleраньше не знал:
fullFence, acquireFence, releaseFence, loadLoadFenceИ storeStoreFence.
Проведя некоторые исследования, особенно в отношении концепции барьеров / заборов памяти (я слышал о них ранее, да; но никогда не использовал их, поэтому был совершенно незнаком с их семантикой), я думаю, что у меня есть общее представление о том, для чего они , Тем не менее, поскольку мои вопросы могут возникнуть из-за неправильного представления, я хочу убедиться, что я правильно понял в первую очередь:
Барьеры памяти переупорядочивают ограничения относительно операций чтения и записи.
Барьеры памяти можно разделить на две основные категории: однонаправленные и двунаправленные барьеры памяти, в зависимости от того, устанавливают ли они ограничения на чтение или запись, или на то и другое.
C ++ поддерживает множество барьеров памяти , однако они не совпадают с теми, которые предоставляет
VarHandle. Однако некоторые из имеющихся в наличии барьеров памятиVarHandleобеспечивают эффекты упорядочения , совместимые с соответствующими им барьерами памяти C ++.#fullFenceсовместим сatomic_thread_fence(memory_order_seq_cst)#acquireFenceсовместим сatomic_thread_fence(memory_order_acquire)#releaseFenceсовместим сatomic_thread_fence(memory_order_release)#loadLoadFenceи не#storeStoreFenceимеют совместимого контраргумента C ++
Слово « совместимость» кажется здесь действительно важным, поскольку семантика явно отличается, когда дело доходит до деталей. Например, все барьеры C ++ являются двунаправленными, в то время как барьеры Java не являются (обязательно).
- Большинство барьеров памяти также имеют эффекты синхронизации. Это особенно зависит от используемого типа барьера и ранее выполненных инструкций барьера в других потоках. Поскольку полное значение, которое имеет инструкция для барьера, зависит от аппаратного обеспечения, я буду придерживаться барьеров более высокого уровня (C ++). Например, в C ++ изменения, сделанные до инструкции барьера освобождения , видны потоку, выполняющему инструкцию барьера получения .
Верны ли мои предположения? Если да, то мои следующие вопросы:
Существуют ли барьеры памяти в
VarHandleкакой-либо синхронизации памяти?Независимо от того, вызывают ли они синхронизацию памяти или нет, для чего могут быть полезны ограничения переупорядочения в Java? Модель памяти Java уже дает некоторые очень строгие гарантии в отношении упорядочения, когда задействованы изменчивые поля, блокировки или
VarHandleподобные операции#compareAndSet.
В случае, если вы ищете пример: вышеупомянутый BufferedSubscription, внутренний класс SubmissionPublisher(источник связан с выше), установил полный забор в строке 1079 (функция growAndAdd; поскольку связанный веб-сайт не поддерживает идентификаторы фрагмента, просто CTRL + F для него ). Однако для меня неясно, для чего это.
plain -> opaque -> release/acquire -> volatile (sequential consistency).