2010-04-05 18 views
41

El modelo de memoria java indica que escribir un int es atómico: Es decir, si escribe un valor para él (que consta de 4 bytes) en un hilo y lo lee en otro, lo hará obtener todos los bytes o ninguno, pero nunca 2 bytes nuevos y 2 bytes viejos o tal.Está escribiendo una referencia atómica en máquinas virtuales de 64 bits

Esto no está garantizado para long. Aquí, escribir 0x1122334455667788 en una variable que contenga 0 antes podría dar como resultado otro hilo que lea 0x112233440000000 o 0x0000000055667788.

Ahora, la especificación no obliga a las referencias de objetos a ser int o long-sized. Por motivos de seguridad de tipo, sospecho que se garantiza que se escribirán atómicamente, pero en una VM de 64 bits estas referencias podrían ser valores de 64 bits muy buenos (simplemente direcciones de memoria).

Ahora aquí están mis preguntas:

  • ¿Hay especificaciones modelo de memoria que cubren este (que no he encontrado)?
  • ¿Las escrituras largas son sospechosas de ser atómicas en máquinas virtuales de 64 bits?
  • ¿Las máquinas virtuales están forzadas a asignar referencias a 32 bits?

Saludos, Steffen

+2

@Steffen Heil: nitpicking pero tenga en cuenta que no todas las referencias son de 64 bits internamente incluso en 64 bits VM (debido a la increíble cantidad de residuos que se generan referencias 64 bits).Las máquinas virtuales modernas están utilizando compresión/compresión de puntero llamada * "CompressedOops" *: http://wikis.sun.com/display/HotSpotInternals/CompressedOops Así que no estoy en desacuerdo con que * podrían * tener un valor de 64 bits, pero a menudo no lo son. 't (no es que cambie mucho a la respuesta que Dirk publicó). – SyntaxT3rr0r

Respuesta

52

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

A los efectos del modelo de memoria de lenguaje de programación Java, un sola escritura a un valor de largo o doble no volátil se trata como dos escrituras separadas: una para cada mitad de 32 bits. Esto puede dar como resultado una situación donde un hilo ve los primeros 32 bits de un valor de 64 bits de una escritura, y los segundos 32 bits de otra escritura.

Las escrituras y las lecturas de valores largos y dobles volátiles son siempre atómicas.

Las escrituras de las referencias son siempre atómicas, independientemente de si están implementadas como valores de 32 bits o de 64 bits.

Algunas implementaciones pueden encontrar conveniente dividir una única acción de escritura en un largo o doble valor de 64 bits en dos acciones de escritura en valores de 32 bits adyacentes. Por razones de eficiencia, este comportamiento es específico de la implementación; una implementación de Java Virtual Machine es libre de realizar escrituras a valores largos y dobles atómicamente o en dos partes.

Se recomienda que las implementaciones de la Máquina Virtual Java eviten dividiendo los valores de 64 bits cuando sea posible. Los programadores son alentados a declarar valores compartidos de 64 bits como volátiles o sincronizar sus programas correctamente para evitar posibles complicaciones.

(Énfasis añadido)

+0

Ok, me perdí el punto en las especificaciones de nuevo. A mi parecer, estoy demasiado cansado y debería dormir en lugar de hacer preguntas ... Gracias por el puntero. (OTRA VEZ) –

+1

Si "Las escrituras y lecturas de las referencias son siempre atómicas, independientemente de si están implementadas como valores de 32 o 64 bits", ¿por qué tenemos la clase AtomicReference (https://docs.oracle.com/javase/ 7/docs/api/java/util/concurrent/atomic/AtomicReference.html)? Solo por los métodos getAndSet/compareAndSet? –

+0

No ver los valores de referencia rasgados es solo una parte de la imagen. El 'AtomicReference' existe principalmente para su API de sincronización (el' compareAndSet' aludido), @ mc.android.developer, y no hay "solo" aquí. Esa es realmente la parte importante. – Dirk

Cuestiones relacionadas