Question

Nous avons rencontré un étrange problème avec ConcurrentHashMap, où les deux fils semble être l'appel de put(), et puis d'attendre pour toujours à l'intérieur de la méthode Unsafe.park().De l'extérieur, il ressemble à un blocage à l'intérieur de ConcurrentHashMap.

Nous avons vu cela se produire une fois si loin.

Quelqu'un peut penser à tout ce qui pourrait causer ces symptômes?

MODIFIER:Le thread dump pour le fils est ici:

"[redacted] Thread 2" prio=10 tid=0x000000005bbbc800 nid=0x921 waiting on condition [0x0000000040e93000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00002aaaf1207b40> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:747)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:778)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1114)
    at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:186)
    at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
    at java.util.concurrent.ConcurrentHashMap$Segment.put(ConcurrentHashMap.java:417)
    at java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:883)
    at [redacted]


"[redacted] Thread 0" prio=10 tid=0x000000005bf38000 nid=0x91f waiting on condition [0x000000004151d000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00002aaaf1207b40> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:158)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:747)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:778)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1114)
    at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:186)
    at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:262)
    at java.util.concurrent.ConcurrentHashMap$Segment.put(ConcurrentHashMap.java:417)
    at java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:883)
    at [redacted]
Était-ce utile?

La solution

Peut-être pas la réponse que vous voulez, mais cela peut être une JVM bug.Voir

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6865591

Autres conseils

Je ne pense pas que c'est ce qui se passe dans votre cas, mais il est possible d'écrire un blocage avec une seule instance de ConcurrentHashMap, et il suffit qu'un seul fil!M'a gardé coincé pendant un certain temps.

Disons que vous êtes à l'aide d'un ConcurrentHashMap<String, Integer> pour calculer un histogramme.Vous pourriez faire quelque chose comme ceci:

int count = map.compute(key, (k, oldValue) -> {
    return oldValue == null ? 1 : oldValue + 1;
});

Qui fonctionne très bien.

Mais disons que vous décidez plutôt que de l'écrire comme ceci:

int count = map.compute(key, (k, oldValue) -> {
    return map.putIfAbsent(k, 0) + 1;
});

Vous aurez maintenant un 1-blocage de thread avec une pile comme ceci:

Thread [main] (Suspended)   
    owns: ConcurrentHashMap$ReservationNode<K,V>  (id=25)   
    ConcurrentHashMap<K,V>.putVal(K, V, boolean) line: not available    
    ConcurrentHashMap<K,V>.putIfAbsent(K, V) line: not available    
    ConcurrentHashMapDeadlock.lambda$0(ConcurrentHashMap, String, Integer) line: 32 
    1613255205.apply(Object, Object) line: not available    
    ConcurrentHashMap<K,V>.compute(K, BiFunction<? super K,? super V,? extends V>) line: not available  

Dans l'exemple ci-dessus, il est facile de voir que nous sommes d'une tentative de modifier la carte à l'intérieur de l'atome de modification, ce qui semble une mauvaise idée.Cependant, si il ya une centaine de pile d'images de l'événement-rappels entre l'appel de map.compute et map.putIfAbsent, alors il peut être assez difficile à traquer.

Package Dangereux est originaire, une mise en œuvre dépend de la plate-forme.

L'arrêt brutal d'une troisième fil (sur la plate-forme de niveau, excepion n'est pas un problème) qui a acquis un verrou sur la carte causes d'une telle situation - l'état de la serrure est cassée, deux autres threads sont désactivés et en attente pour quelqu'un d'appeler Dangereux.id() (Et qui n'arrivera jamais).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top