2010-04-05 9 views
41

Il modello di memoria java richiede che la scrittura di int sia atomica: ovvero, se si scrive un valore (composto da 4 byte) in un thread e lo si legge in un altro, si ottieni tutti i byte o nessuno, ma mai 2 nuovi byte e 2 vecchi byte o simili.Sta scrivendo un riferimento atomico su macchine virtuali a 64 bit

Questo non è garantito per long. In questo caso, la scrittura di 0x1122334455667788 in una variabile contenente 0 prima potrebbe comportare un'altra lettura di thread 0x112233440000000 o 0x0000000055667788.

Ora le specifiche non impongono che i riferimenti agli oggetti siano int sia di lunga durata. Per motivi di sicurezza del tipo, sospetto che siano garantiti per essere scritti atomicamente, ma su una macchina virtuale a 64 bit questi riferimenti potrebbero essere molto buoni a 64 bit (solo indirizzi di memoria).

Ora qui sono le mie domande:

  • Esistono specifiche modello di memoria che coprono questo (che non ho trovato)?
  • Le sospette scritture lunghe sono atomiche su macchine virtuali a 64 bit?
  • Le macchine virtuali sono forzate a mappare i riferimenti a 32 bit?

saluti, Steffen

+2

@Steffen Heil: fare i difficili, ma di notare che non tutti i riferimenti sono a 64 bit internamente anche a 64 bit VM (a causa della straordinaria quantità di rifiuti 64 riferimenti bit stanno generando).Le moderne macchine virtuali usano la compressione del puntatore/compressione di riferimento chiamata * "CompressedOops" *: http://wikis.sun.com/display/HotSpotInternals/CompressedOops Quindi non sono d'accordo sul fatto che * potrebbero * avere un valore a 64 bit ma spesso non sono 't (non che cambia molto alla risposta che Dirk ha pubblicato). – SyntaxT3rr0r

risposta

52

Vedi JLS section 17.7: Non-atomic Treatment of double and long

Ai fini del modello di memoria linguaggio di programmazione Java, un singola scrittura a un valore lungo o doppio non volatile viene trattato come due scritture separate: una per ciascuna metà a 32 bit. Ciò può comportare una situazione in cui un thread vede i primi 32 bit di un valore a 64 bit da una scrittura e i secondi 32 bit da un'altra scrittura.

Scritture e letture di valori volatili lunghi e doppi sono sempre atomici.

Le scritture e le letture dei riferimenti sono sempre atomiche, indipendentemente da se sono implementate come valori a 32 o 64 bit.

Alcune implementazioni possono trovare conveniente dividere una singola azione di scrittura su un valore lunga o doppia a 64 bit in due operazioni di scrittura su valori a 32 bit adiacenti. Per motivi di efficienza, questo comportamento è specifico per l'implementazione; un'implementazione della Java Virtual Machine è libera di eseguire scritture a valori lunghi e doppi atomicamente o in due parti.

Le implementazioni della Java Virtual Machine sono incoraggiate ad evitare dividendo i valori a 64 bit laddove possibile. I programmatori sono invitati a a dichiarare valori di 64 bit condivisi come volatili o a sincronizzare i loro programmi correttamente per evitare possibili complicazioni.

(enfasi aggiunta)

+0

Ok, ho mancato di nuovo il punto nelle specifiche. Mi sembra, sono troppo stanco e dovrei dormire invece di fare domande ... Grazie per il puntatore. (ANCORA) –

+1

Se "Scrittura e lettura dei riferimenti sono sempre atomici, indipendentemente dal fatto che siano implementati come valori 32 o 64 bit.", Perché abbiamo classe AtomicReference (https://docs.oracle.com/javase/ 7/docs/api/java/util/concorrente/Atomic/AtomicReference.html)? Solo a causa dei metodi getAndSet/compareAndSet? –

+0

La mancata visualizzazione dei valori di riferimento incompleti è solo una parte dell'immagine. Il 'AtomicReference' esiste principalmente per la sua API di sincronizzazione (il' compareAndSet' a cui hai alluso), @ mc.android.developer, e qui non c'è "solo". Questa è in realtà la parte importante. – Dirk

Problemi correlati