2010-03-05 10 views
5

En Java existe una clase AtomicReference. ¿Significa esto que establecer una referencia NO es una operación atómica en sí misma?AtomicReference en Java: ¿es necesario para establecer una referencia en un entorno seguro para subprocesos?

por ejemplo, está presente no seguro para subprocesos (suponiendo que el valor devuelto no se puede modificar) ?:

public void someMethod() 
{ 
    this.someList = Collections.unmodifiableList(new LinkedList<Object>()); 
} 

public List<Object> getReadOnlyList() 
{ 
    return someList; 
} 

¿Y en C#?

+3

Su ejemplo no es completamente seguro para subprocesos. Si la lista no se publica de forma segura, es posible que no lea los contenidos correctamente (aunque la implementación de 'LinkedList' puede permitirle salirse con la suya si está vacía). –

+0

@Tom: ¿quiere decir que otros subprocesos pueden obtener un valor viejo en caché para el campo someList, o que el campo someList puede estar "medio escrito"? – radai

+0

@ hatchetman82 Quiero decir que después de leer la nueva referencia, es posible que el objeto al que apunta no se haya actualizado por completo. Entonces, si fuera inseguro público 'nuevo java.awt.Point (1, 2)', podría leer el objeto en otro hilo, pero los campos 'x' y' y' pueden seguir siendo cero. –

Respuesta

3

De acuerdo con la Java Language Specification, version 3.0, Section 17.7:

le escriba y lee las referencias son siempre atómica, independientemente de si se implementan como 32 o 64 valores de bits.

AtomicReference permite realizar una comparación y establecerla como una acción atómica.

Esto no es multi-hilo:

public boolean changeList(List<Object> oldValue, List<Object> newValue) { 
    if (this.someList == oldValue) { 
     // someList could be changed by another thread after that compare, 
     // and before this set 
     this.someList = newValue; 
     return true; 
    } 
    return false; 
} 
+1

Podría hacer con algunos genéricos en el parámetro 'List'. –

+0

use public boolean changeList (List oldValue, List newValue) en su lugar – Lombo

1

Si no se utiliza la palabra clave o AtomicReference volátil y el hilo de la lectura de la referencia no es la que escribió a ella, no hay garantía de que la lectura thread verá el valor actualizado.

Esto es especialmente cierto en un entorno de procesador múltiple. La palabra clave volátil y AtomicReference (que usa las características volátiles internamente para las operaciones básicas de configuración/obtención) imponen una barrera de memoria y un vaciado de caché, asegurándose de que el valor actualizado sea visible en la memoria principal.

3

Lo que a veces se pasa por alto package description para java.util.concurrent.atomic detalla algunos usos comunes.

Adición: Del mismo modo, package description para java.util.concurrent resume convenientemente varios puntos esenciales detallados en JLS §17.

Además, tenga en cuenta el beneficio potencial de Final Field Semantics si se supone que su List es inmutable y se puede hacer una referencia al mismo final.

1

En cuanto a C#, encontré la respuesta a esto yo mismo. Establecer una referencia es una operación atómica según la sección 5.5 de la especificación del lenguaje C#.

"Las lecturas y escrituras de los siguientes tipos de datos son atómicos: bool, char, byte, sbyte, corto, ushort, uint, int, float y tipos de referencia. Además, lee y escribe tipos enum con un subyacente El tipo en la lista anterior también es atómico. No se garantiza que las lecturas y escrituras de otros tipos, incluyendo long, ulong, double y decimal, así como tampoco los tipos definidos por el usuario, sean atómicos. Aparte de las funciones de la biblioteca diseñadas para ese fin , no hay garantía de lectura-modificación-escritura atómica, como en el caso de incremento o disminución ".

+0

La pregunta es acerca de la seguridad del hilo, no la atomicidad. Por ejemplo, leer una variable de referencia no sincronizada en Java puede ser atómica pero ** no ** segura para subprocesos. –

+0

Cf. http://java.sun.com/docs/books/jls/third_edition/html/memory.html#17.7 – trashgod

+0

El punto es que la atomicidad garantiza que leerá el valor anterior de la referencia (o nulo) o el nuevo valor de la referencia pero nunca parte de una y parte de la otra. –

3

¿Esto significa que establecer una referencia NO es una operación atómica en sí misma?

Establecer una variable de referencia es atómica, pero una operación atómica no es necesariamente segura para subprocesos. Dejame explicar.

Atómico significa que cualquier observador (hilo) ve el valor anterior o el nuevo valor de la variable, y no algo más. No significa que todos los observadores ven el nuevo valor cuando miran la variable. (Y como @Tom señala, la atomicidad de la variable de referencia no dice nada sobre las propiedades de atomicidad del objeto al que hace referencia).

Para que todos los observadores vean el nuevo valor en la variable, debe haber alguna sincronización en marcha en. Para una actualización de una variable, esto sucederá si:

  • la variable se declara como volatile, o
  • acceso/cambios a la variable están sincronizadas por el mismo bloqueo del monitor primitiva.

Una variable que se envuelve en la clase correspondiente "AtomicXxx" también será seguro para subprocesos, aunque normalmente utiliza una de estas clases, si se quiere evitar bloqueos y que quiere hacer cosas tales como atómica "comparar y reemplazar".

De nuevo, esto solo se aplica a la seguridad de la hebra de la referencia del objeto. Si el estado del objeto no es también correctamente sincronizado, un hilo podría ver valores obsoletos para los atributos del objeto, etcétera.

Cuestiones relacionadas