Mentre cercavo di capire come SubmissionPublisher
( codice sorgente in Java SE 10, OpenJDK | docs ), una nuova classe aggiunta a Java SE nella versione 9, è stata implementata, mi sono imbattuto in alcune chiamate API di VarHandle
cui non ero a conoscenza in precedenza:
fullFence
, acquireFence
, releaseFence
, loadLoadFence
E storeStoreFence
.
Dopo aver fatto qualche ricerca, in particolare per quanto riguarda il concetto di barriere / recinzioni di memoria (ne ho sentito parlare in precedenza, sì; ma non le ho mai usate, quindi non avevo abbastanza familiarità con la loro semantica), penso di avere una comprensione di base di ciò per cui sono . Tuttavia, poiché le mie domande potrebbero derivare da un malinteso, voglio assicurarmi di averlo capito bene in primo luogo:
Le barriere di memoria stanno riordinando i vincoli relativi alle operazioni di lettura e scrittura.
Le barriere di memoria possono essere classificate in due categorie principali: barriere di memoria unidirezionali e bidirezionali, a seconda che stabiliscano vincoli su letture o scritture o su entrambi.
C ++ supporta una serie di barriere di memoria , tuttavia, queste non corrispondono a quelle fornite da
VarHandle
. Tuttavia, alcune delle barriere di memoria disponibili nelVarHandle
fornire effetti di ordinamento che sono compatibili con i corrispondenti barriere memoria C ++.#fullFence
è compatibile conatomic_thread_fence(memory_order_seq_cst)
#acquireFence
è compatibile conatomic_thread_fence(memory_order_acquire)
#releaseFence
è compatibile conatomic_thread_fence(memory_order_release)
#loadLoadFence
e#storeStoreFence
non hanno una controparte C ++ compatibile
La parola compatibile sembra davvero importante qui poiché la semantica differisce chiaramente quando si tratta di dettagli. Ad esempio, tutte le barriere C ++ sono bidirezionali, mentre le barriere Java non lo sono (necessariamente).
- La maggior parte delle barriere di memoria hanno anche effetti di sincronizzazione. Questi dipendono soprattutto dal tipo di barriera utilizzato e dalle istruzioni di barriera precedentemente eseguite in altri thread. Dato che le implicazioni complete di un'istruzione barriera sono specifiche dell'hardware, rimarrò con le barriere di livello superiore (C ++). In C ++, ad esempio, le modifiche apportate prima di un'istruzione di barriera di rilascio sono visibili a un thread che esegue un'istruzione di acquisizione di barriera.
I miei presupposti sono corretti? In tal caso, le mie domande risultanti sono:
Le barriere di memoria disponibili
VarHandle
causano qualche tipo di sincronizzazione della memoria?Indipendentemente dal fatto che causino o meno la sincronizzazione della memoria, a cosa possono essere utili i vincoli di riordino in Java? Il modello di memoria Java offre già alcune garanzie molto forti in merito all'ordinamento quando sono coinvolti campi volatili, blocchi o
VarHandle
operazioni simili#compareAndSet
.
Nel caso in cui tu stia cercando un esempio: la suddetta BufferedSubscription
, una classe interna di SubmissionPublisher
(fonte collegata sopra), ha stabilito un recinto completo nella riga 1079 (funzione growAndAdd
; poiché il sito Web collegato non supporta identificatori di frammenti, solo CTRL + F per esso ). Tuttavia, non è chiaro per me a cosa serva.
plain -> opaque -> release/acquire -> volatile (sequential consistency)
.