2011-05-13 3 views
6

Je lis pour la concurence depuis hier et je ne sais pas beaucoup de choses ... Cependant, certaines choses commencent à se clarifier ...
Je comprends pourquoi le double contrôle de verrouillage n'est pas sûr (je me demande quelle est la propabilité la condition rare de se produire), mais fixe volatils la question 1.5 + ....
mais je me demande si cela se produit avec putifAbsentPourquoi ConcurrentHashMap.putifAbsent est sécuritaire?

comme ...

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

Alors est-ce qui garantit que myObj serait 100% intialiased quand un autre thread fait un cHashM.get() ??? Parce qu'il pourrait avoir une référence isnt complètement initialisés (le double problème de verrouillage à cocher)

Répondre

3

Si vous invoquez concurrentHashMap.get(key) et retourne un objet, cet objet est garanti soit complètement initialisé. Chaque put (ou putIfAbsent) obtiendra un verrou spécifique au bucket et ajoutera l'élément aux entrées du bucket.

Maintenant, vous pouvez passer par le code et notez que la méthode get n'obtient pas ce même verrou. Vous pouvez donc soutenir qu'il peut y avoir une lecture périmée, ce qui n'est pas vrai non plus. La raison en est que la valeur dans l'entrée elle-même est volatile. Donc, vous serez sûr d'obtenir le plus à jour lire.

+0

Donc, si je comprends bien, il n'y a pas de problème, comme dans le paradigme classique du double contrôle? – GorillaApe

+0

@Parhs: Droit, il n'y a pas de problème. – ColinD

+0

Vous avez raison. Vous avez effectivement répondu vous-même dans votre question avec 'mais volatile corrige le problème en 1.5 + 'Comme la valeur retournée par le CCHM est une valeur volatile, elle est aussi sûre de l'initialisation partielle. –

1

Je ne suis pas un expert, mais regardant la mise en œuvre de Segment dans ConcurrentHashMap Je vois que le champ volatilecount semble être utilisé pour assurer une bonne visibilité entre les fils. Toutes les opérations de lecture doivent lire le champ count et toutes les opérations d'écriture doivent y être écrites. D'après les commentaires dans la classe:

 
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 La méthode dans ConcurrentHashMap est la méthode check-if-absent-then-set. C'est une opération atomique. Mais pour répondre à la partie suivante: "Alors cela garantit-il que myObj serait 100% intialiased quand un autre thread fait un cHashM.get()", cela dépendra du moment où l'objet est placé dans la HashMap. Habituellement, il y a une précédence précédente, c'est-à-dire, si l'appelant obtient la première avant que l'objet ne soit placé dans la carte, alors null serait retourné, sinon la valeur serait retournée.

+0

null à être retourné ne serait pas un prb mais une référence à un objet non entièrement construit-initiliased serait. (le problème avec le double contrôle de verrouillage) – GorillaApe

2

La partie pertinente de la documentation est la suivante:

effets de cohérence de la mémoire: Comme autres collections concurrentes, les actions dans un fil avant de placer un objet dans un ConcurrentMap comme une clé ou une valeur les actions qui ont eu lieu avant l'accès ou la suppression de cet objet de la ConcurrentMap dans un autre thread .

- java.util.ConcurrentMap

Alors, oui, vous avez votre arrive-avant relation.

Questions connexes