2013-03-04 7 views

risposta

18

La mia risposta precedente era errata, come spiegato nel commento di juancn:

Questa è la differenza tra le classi e Atomic* accesso volatile. L'assegnazione di riferimento è atomica solo nel senso che non si può verificare alcuna lacerazione di parole, ma non ci sono garanzie di visibilità o riordino. Java garantisce le scritture atomiche in questo senso limitato per tutti i tipi primitivi e riferimenti ma non per lungo/doppio (anche se in VM a 64 bit penso che siano sempre atomici).

risposta precedente

E 'necessario, soprattutto per compareAndSet e getAndSet metodi. Non è possibile farlo atomicamente altrimenti (sono necessarie 2 operazioni).

+2

+1 che è esattamente la ragione per tutte le Atomic ... '' classi. –

+1

@JimGarrison non esattamente. le assegnazioni long/float/double non sono atomiche. Assegnerà le due parole all'indirizzo a cui è assegnato in un ordine arbitrario (sarà necessario cercare informazioni sul modello di memoria java). Se hai due thread in competizione per scrivere un valore per quell'indirizzo, puoi ottenere una parola che ha avuto origine nel thread 1 e quindi la seconda parola che ha avuto origine nel thread 2, risultante in un valore di spazzatura – searchengine27

+3

* Può * essere assegnato in un ordine arbitrario. Molte piattaforme hardware supportano larghezze di parola a 64 bit. E su quella nota, questo vale solo per il lungo e il doppio. Non mobile, che è largo 32 bit. –

21

Perché utilizzare AtomicReference se l'assegnazione di riferimento è atomica in java?

È necessario quando la decisione su cui si basa la creazione del nuovo valore può dipendere dal valore precedente del riferimento. Ad esempio, quando si implementa una struttura di dati come LinkedList, non si vuole impostare la testa su un nuovo nodo che si riferisce al nodo precedente. Nel tempo che intercorre tra la lettura del nodo precedente e l'impostazione della testa in quella nuova, un altro thread potrebbe aver aggiornato contemporaneamente il valore del riferimento della testina. Se il nostro thread non fosse a conoscenza di questo cambiamento, andrebbe perso.

Abbiamo bisogno di volatilità per avere un sistema di riferimento atomico?

L'operazione stessa verrebbe eseguita atomica sul core della CPU che la esegue ma non ci sono garanzie che i thread su altri core ne siano a conoscenza nella prossima lettura.

+1

Inoltre, le scritture sui riferimenti sono sempre atomiche, prese dal JLS: le scritture e le letture dei riferimenti sono sempre atomiche, indipendentemente dal fatto che siano implementate come valori a 32 o 64 bit. – SakeSushiBig

+0

+1. Penso che la tua risposta sia ottima, ma sarebbe ancora meglio dimostrare come la classe AtomicReference entra in gioco per l'esempio che hai dato. – nhahtdh

+0

Controlla questo link: http://stackoverflow.com/questions/31042696/when-does-a-reference-need-to-be-atomic?noredirect=1&lq=1 –

2

La ragione è che anche se il riferimento è atomico, è atomico in un senso molto stretto.

Se un thread scrive un riferimento non volatile, ciò che è garantito è che gli altri thread vedranno l'intera scrittura o non lo vedano affatto (nessuna parola strappo/spazzatura).

Ma in nessun caso è garantito che nessun altro thread lo vedrà mai né che saranno visti nello stesso ordine.

Un AtomicReference fornisce garanzie molto più forti (oltre alle operazioni di CAS), in sostanza, si comportano come volatile:

  • qualsiasi scrittura che è accaduto nel thread A prima di una scrittura volatili sono visibili in filo B dopo una lettura successiva volatili di quel
  • operazioni volatili variabili non possono essere riordinate
Problemi correlati