代码之家  ›  专栏  ›  技术社区  ›  Simon Nickerson

ConcurrentHashMap有可能变成“死锁”吗?

  •  21
  • Simon Nickerson  · 技术社区  · 14 年前

    我们遇到了一个奇怪的问题 ConcurrentHashMap ,其中两个线程似乎正在调用 put() Unsafe.park() .

    有人能想到什么能引起这些症状吗?

    编辑 :相关线程的线程转储如下:

    "[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]
    
    3 回复  |  直到 14 年前
        1
  •  4
  •   Jim Garrison    14 年前

    可能不是您想要的答案,但这可能是一个JVM错误。看到了吗

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

        2
  •  11
  •   Ned Twigg    8 年前

    ConcurrentHashMap ,它只需要一个线程!让我困了好一阵子。

    假设你用的是 ConcurrentHashMap<String, Integer> 计算直方图。你可以这样做:

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

    但假设你决定这样写:

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

    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  
    

    在上面的例子中,很容易看出我们试图修改原子修改中的映射,这看起来是个坏主意。但是,如果在调用 map.compute map.putIfAbsent ,那么就很难找到了。

        3
  •  3
  •   Nulldevice    14 年前

    突然终止第三个线程(在平台级别上,异常不是问题)从而在map上获得了一个锁,这可能会导致这种情况-锁的状态被破坏,另外两个线程被禁用,并等待有人调用Unsafe.unpark()(这永远不会发生)。