2011-05-13 11 views
6

He estado leyendo para la concurencia desde ayer y no sé muchas cosas ... Sin embargo, algunas cosas están empezando a ponerse claras ...
Entiendo por qué el doble bloqueo no es seguro (me pregunto cuál es la propagación de la rara condición que ocurra), pero volátiles corrige el problema en 1.5 + ....
pero me pregunto si esto ocurre con putifAbsent¿Por qué ConcurrentHashMap.putifAbsent es seguro?

como ...

myObj = new myObject("CodeMonkey"); 
cHashM.putIfAbsent("keyy",myObj); 

Luego hace esto asegura que myObj sería del 100% intialiased cuando otro hilo hace un cHashM.get() ??? Porque podría tener una referencia isnt completamente inicializado (el doble problema de bloqueo de verificación)

Respuesta

3

Si se invoca concurrentHashMap.get(key) y devuelve un objeto, ese objeto se garantiza para estar totalmente inicializado. Cada put (o putIfAbsent) obtendrá un bloqueo específico del depósito y anexará el elemento a las entradas del depósito.

Ahora puede revisar el código y observar que el método get no obtiene este mismo bloqueo. Entonces puedes argumentar que puede haber una lectura desactualizada, eso tampoco es verdad. La razón aquí es que el valor dentro de la entrada en sí es volátil. Por lo tanto, asegúrese de obtener la lectura más actualizada.

+0

Entonces, si entiendo correctamente, no hay ningún problema, como en el clásico paradigma de bloqueo de doble verificación. – GorillaApe

+0

@Parhs: Correcto, no hay problema. – ColinD

+0

Tiene razón. Usted mismo lo respondió en su pregunta con 'pero volátil corrige el problema en 1.5 + 'Dado que el valor devuelto por el CCHM es un valor volátil, también está a salvo de la inicialización parcial. –

1

no soy un experto en esto, pero mirando a la implementación de Segment en ConcurrentHashMap veo que el campo countvolatile parece utilizarse para garantizar la visibilidad adecuada entre los hilos. Todas las operaciones de lectura deben leer el campo count y todas las operaciones de escritura deben escribir en él. A partir de los comentarios de la clase:

 
Read operations can thus proceed without locking, but rely 
on selected uses of volatiles to ensure that completed 
write operations performed by other threads are 
noticed. For most purposes, the "count" field, tracking the 
number of elements, serves as that volatile variable 
ensuring visibility. This is convenient because this field 
needs to be read in many read operations anyway: 

    - All (unsynchronized) read operations must first read the 
    "count" field, and should not look at table entries if 
    it is 0. 

    - All (synchronized) write operations should write to 
    the "count" field after structurally changing any bin. 
    The operations must not take any action that could even 
    momentarily cause a concurrent read operation to see 
    inconsistent data. This is made easier by the nature of 
    the read operations in Map. For example, no operation 
    can reveal that the table has grown but the threshold 
    has not yet been updated, so there are no atomicity 
    requirements for this with respect to reads. 
2

putIfAbsent método en ConcurrentHashMap es el método de comprobación si falta el conjunto. Es una operación atómica. Pero para responder a la siguiente parte: "Entonces, esto garantiza que myObj sea 100% intialiased cuando otro hilo hace un cHashM.get()", dependería de cuando el objeto se coloque en el HashMap. Por lo general, hay un hecho anterior a la precedencia, es decir, si la persona que llama obtiene primero antes de que el objeto se coloque en el mapa, entonces se devolverá null, de lo contrario se devolverá el valor.

+0

null que se devolverá no sería un prb pero sería una referencia a un objeto initiliased no completamente construido. (el problema con el doble bloqueo de bloqueo) – GorillaApe

2

La parte pertinente de la documentación es la siguiente:

efectos de coherencia de la memoria: Como con otros colecciones concurrentes, acciones en un hilo antes de la colocación de un objeto en un ConcurrentMap como una clave o el valor suceder antes de acciones posteriores a el acceso o la eliminación de ese objeto desde el mapa simultáneo en otro hilo .

- java.util.ConcurrentMap

lo tanto, sí que tienen su sucede antes relación.