Поки намагалися зрозуміти, як 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)
.