AtomicInteger lazySet vs. set
-
13-09-2019 - |
Domanda
Qual è la differenza tra i lazySet
e set
metodi di AtomicInteger
? La documentazione rel="noreferrer"> non ha molto da dire su lazySet
:
Alla fine imposta al valore indicato.
Sembra che il valore memorizzato non viene immediatamente impostata al valore desiderato, ma sarà invece programmato per essere impostato po 'di tempo in futuro. Ma, che cosa è l'uso pratico di questo metodo? Qualsiasi esempio?
Soluzione
"JDK-6.275.329: Aggiungere metodi lazySet alle classi atomiche" :
Come probabilmente l'ultimo piccolo JSR166 follow-up per la Mustang, abbiamo aggiunto un metodo "lazySet" per le classi Atomic (AtomicInteger, AtomicReference, ecc). Si tratta di una nicchia metodo che a volte è utile quando il codice messa a punto utilizzando non bloccante strutture di dati. La semantica è che la scrittura è garantito di non essere ri-ordinati con qualsiasi precedente scrittura, ma possono essere riordinate operazioni successive (O equivalentemente, potrebbe non essere visibile ad altri thread) fino si verifica qualche altro scrittura volatile o azione sincronizzazione).
Il caso d'uso principale è per annullamento dei fuori campi di nodi non bloccante strutture dati unicamente a fini di evitare A lungo termine la conservazione della spazzatura; si applica quando è innocuo se altri thread vedono valori non nulli per un po ', ma si sarebbe come per garantire che le strutture sono infine GCable. in tale i casi, è possibile ottenere prestazioni migliori, evitando i costi della nullo volatili-scrittura. Ci sono alcuni altri casi di utilizzo in tal senso per non riferimento basati Atomics pure, in modo che il metodo è supportato in tutte le classi AtomicX.
Per le persone che amano pensare di queste operazioni in termini di barriere a livello macchina su multiprocessori comuni, lazySet fornisce una barriera negozio negozio precede (che è o un no-op o molto a buon mercato su piattaforme attuali), ma non barriera negozio carico (che di solito è la parte costosa di volatili-scrittura).
Altri suggerimenti
lazySet possono essere utilizzati per la comunicazione filo tra RMW, perché xchg è atomico, come per la visibilità, quando processo thread di scrittura modificare una posizione linea di cache, il processore del filo lettore vedrà alla lettura successiva, perché il protocollo coerenza della cache di Intel CPU la garanzia funziona LazySet, ma la linea di cache verrà aggiornato alla prossima lettura, ancora una volta, la CPU deve essere abbastanza moderno.
http://sc.tamu.edu/systems/eos/nehalem.pdf Nehalem che è una piattaforma multi-processore, i processori hanno la capacità di “snoop” (intercettare) il bus domicilio altro processore di accessi alla memoria di sistema e alle loro cache interne. Usano questa capacità snooping per mantenere le loro cache interne coerente sia con la memoria di sistema e con le cache in altri processori interconnessi. Se attraverso snooping un processore rileva un altro processore si propone di scrivere in una posizione di memoria che attualmente è nella cache a stato condiviso, il processore snooping invaliderà il suo blocco di cache costringendolo a eseguire una linea di cache riempire la prossima volta che si accede alla stessa posizione di memoria .
Oracle JDK hotspot per l'architettura cpu x86 ->
lazySet == == unsafe.putOrderedLong xchg RW (istruzione asm che servono da barriera morbido costano 20 cicli su nehelem Intel CPU)
su x86 (x86_64) una tale barriera è molto più conveniente prestazioni-saggio di volatili o AtomicLong getAndAdd,
In un un produttore, uno scenario di coda dei consumatori, XCHG barriera morbido può forzare la linea di codici prima della lazySet (sequenza + 1) per filo produttore accadere prima alcun codice discussione consumatore che consumerà (lavoro sopra) i nuovi dati Naturalmente filo consumatore dovrà controllare atomicamente quella sequenza produttore è stato incrementato di esattamente un utilizzando un compareAndSet (sequenza, la sequenza + 1).
Ho tracciato dopo il codice sorgente di Hotspot per trovare l'esatta mappatura del lazySet in codice cpp: http: // hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/prims/unsafe.cpp Unsafe_setOrderedLong -> definizione SET_FIELD_VOLATILE -> OrderAccess: release_store_fence. Per x86_64, OrderAccess: release_store_fence è definito come utilizzando l'istruzione xchg.
Si può vedere come è esattamente definito in jdk7 (Doug Lea sta lavorando su del nuovo materiale per JDK 8): http: //hg.openjdk.java.net/jdk7/jdk7/hotspot/file/4fc084dac61e/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp
è anche possibile utilizzare i ISU di smontare il montaggio del codice di lazySet in azione.
C'è un'altra domanda relativa: abbiamo bisogno mfence quando si utilizza xchg
Una più ampia discussione sulle origini e l'utilità del lazySet e putOrdered sottostante può essere trovato qui: http://psy-lob-saw.blogspot.co.uk/2012/12/atomiclazyset-is-performance-win-for.html
Riassumendo: lazySet è una scrittura volatile, debole nel senso che agisce come un negozio negozio e non una recinzione store-carico. Questo si riduce a lazySet essere JIT compilato per un'istruzione MOV che non può essere ri-ordinato dal compilatore piuttosto che l'istruzione notevolmente più costoso utilizzate per un insieme volatile.
Quando si legge il valore si finisce sempre per fare una lettura volatile (con un Atomic * .get () in ogni caso).
lazySet offre un unico produttore di un meccanismo di scrittura volatili coerente, vale a dire che è perfettamente legittimo per un singolo scrittore di utilizzare lazySet per incrementare un contatore, più thread incrementando il contatore stesso dovranno risolvere le scritture concorrenti che utilizzano CAS, che è esattamente cosa succede sotto le coperte di Atomic * per incAndGet.
Concurrent- atomico sintesi pacchetto
lazySet ha gli effetti di memoria di scrittura (assegnazione) una variabile volatile, con la differenza che permette reorderings con successive (ma non precedenti) azioni di memoria che non ci incalzano vincoli riordino con le scritture non volatili ordinarie . Tra gli altri contesti di utilizzo, lazySet può applicare quando annullamento dei out, per il bene di garbage collection, un riferimento che non è mai accedere nuovamente.
Se siete curiosi di sapere lazySet allora lo dovete voi stessi altre spiegazioni troppo
Gli effetti di memoria per gli accessi e gli aggiornamenti di Atomics in generale seguire le regole di volatili, come indicato nella sezione 17.4 di The Java ™ Specifica del linguaggio.
ha gli effetti di memoria di lettura di una variabile volatile.
set ha gli effetti di memoria di scrittura (assegnazione) una variabile volatile.
lazySet ha gli effetti di memoria di scrittura (assegnazione) una variabile volatile, eccetto che permette reorderings con successive (ma non precedenti) azioni di memoria che non ci incalzano riordino vincoli con le scritture non volatili ordinari. Tra l'altro l'uso contesti, lazySet si possono verificare quando annullamento dei out, per il bene della spazzatura collezione, un riferimento che non è mai accedere nuovamente.
weakCompareAndSet si legge atomico e il condizionale scrive una variabile ma non crea alcun accade-prima ordinamenti, lo prevede nessuna garanzia rispetto al precedente o successiva letture e le scritture di tutte le variabili diverse dalla destinazione del weakCompareAndSet. operazioni compareAndSet e tutti gli altri lettura e-aggiornamento come getAndIncrement hanno gli effetti di memoria di lettura e scrittura variabili volatili.
Questa è la mia comprensione, mi corregga se sbaglio:
Si può pensare lazySet()
come "semi" volatile: è fondamentalmente una variabile non volatile in termini di lettura di altri thread, cioè il valore impostato dal lazySet non può essere visibile ad altri thread. Ma diventa instabile quando si verifica un'altra operazione di scrittura (può essere da altri thread).
L'unico impatto della lazySet posso immaginare è compareAndSet
. Quindi, se si utilizza lazySet()
, get()
da altri thread può ancora ottenere il vecchio valore, ma compareAndSet()
avrà sempre il nuovo valore in quanto si tratta di un'operazione di scrittura.
Re: tentativo di muto giù -
Si può pensare a questo come un modo per trattare un campo volatile, come se non fosse stato volatile per un particolare negozio (ad esempio: ref = null;). Operazione
Non è perfettamente accurata, ma dovrebbe essere sufficiente che si potrebbe prendere una decisione tra "OK, io davvero non mi interessa" e "Hmm, fammi pensare che per un po '".