Quale pensi sia il modo migliore per implementare la parte di acquisizione di una coppia di rilascio/acquisizione in Java?Implementazione di un acquisto per un rilascio da Unsafe.putOrdered *()?
Sto provando a modellare alcune delle azioni in un'applicazione mia utilizzando la versione classica/acquisizione semantica (senza StoreLoad
e senza coerenza sequenziale tra thread).
Ci sono un paio di modi per ottenere l'equivalente approssimativo di un rilascio in negozio nel JDK. java.util.concurrent.Atomic*.lazySet()
e il sottostante sun.misc.Unsafe.putOrdered*()
sono gli approcci più spesso citati per farlo. Tuttavia non esiste un modo ovvio per implementare una acquisizione del carico.
Le API JDK che permettono
lazySet()
uso soprattuttovolatile
variabili internamente, quindi il loro negozio-release sono accoppiati con carichi volatili. In teoria, i carichi volatili dovrebbero essere più costosi di quelli acquisiti dal carico e non dovrebbero fornire nulla di più di un puro acquisto del carico nel contesto di un precedente rilascio del negozio.sun.misc.Unsafe
non forniscegetAcquire()*
equivalenti delleputOrdered*()
metodi, anche se tali metodi acquisire sono previste per il prossimo API VarHandles.Qualcosa che suona come funzionerebbe è un carico normale, seguito da
sun.misc.Unsafe.loadFence()
. È piuttosto sconcertante che non l'abbia visto da nessun'altra parte. Questo potrebbe essere collegato al fatto che si tratta di un brutto attacco.
P.S. Comprendo bene che questi meccanismi non sono coperti dal JMM, che non sono sufficienti per mantenere la coerenza sequenziale e che le azioni che creano non sono azioni di sincronizzazione (ad esempio, capisco che per esempio interrompano l'IRIW). Capisco anche che le versioni del negozio fornite da Atomic*/Unsafe
sono più spesso utilizzate sia per i riferimenti che annullano con interesse o negli scenari produttore/consumatore, come meccanismo ottimizzato di trasmissione dei messaggi per alcuni indici importanti.
Grazie per aver trovato il tempo di scrivere una risposta! È pieno di belle informazioni generali, ma mentre è utile per alcune persone, non fornisce alcuna nuova visione non presente nella domanda o nessuna giustificazione sul perché usare il carico specificamente volatile (al contrario di 'loadFence()', o qualcos'altro). –
Forse non capisco esattamente di cosa hai bisogno. Perché non risponde? Non c'è niente da usare tranne vread/'loadFence()'.Usa la lettura volatile se vuoi una semantica/r su una variabile specifica e 'loadFence()' se hai bisogno di barriere solo per es. per set di variabili o * prima * lettura della variabile per evitare il riordino specifico. Modificherò la mia risposta non appena ti avrò capito :) Suppongo di poter rimuovere una parte di no-ops e VH e aggiungere il confronto di 'loadFence()' e vandalo se lo vuoi – qwwdfsad
Ottieni la semantica acquisita da entrambe le letture volatili e ' loadFence() ', e in teoria, il carico volatile può essere più costoso su alcune architetture perché deve essere parte delle azioni di sincronizzazione. Quindi non è così semplice come "basta usare la lettura volatile", almeno non senza argomentazioni leggermente più sostanziali. Ho assunto che volatile read e 'loadFence()' sono le uniche opzioni praticabili, ma spero ancora che qualcuno faccia emergere un'altra opzione interessante. –