Sim*_*son 23 java concurrency concurrenthashmap
我们遇到了一个奇怪的问题ConcurrentHashMap,其中两个线程似乎在调用put(),然后在方法内永远等待Unsafe.park().从外面看,它看起来像是一个僵局ConcurrentHashMap.
到目前为止,我们只看到过这种情况.
谁能想到任何可能导致这些症状的事情?
编辑:相关线程的线程转储在这里:
"[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]
我不认为这是你的情况下发生的事情,但是可以用单个实例写一个死锁,ConcurrentHashMap它只需要一个线程!让我坚持了很长一段时间.
假设您使用a ConcurrentHashMap<String, Integer>来计算直方图.你可能会这样做:
int count = map.compute(key, (k, oldValue) -> {
return oldValue == null ? 1 : oldValue + 1;
});
Run Code Online (Sandbox Code Playgroud)
哪个工作得很好.
但是让我们说你决定改写它:
int count = map.compute(key, (k, oldValue) -> {
return map.putIfAbsent(k, 0) + 1;
});
Run Code Online (Sandbox Code Playgroud)
你现在将得到一个带有这样的堆栈的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
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,我们很容易看到我们试图在原子修改中修改地图,这看起来是个坏主意.但是,如果在调用map.compute和之间有一百个事件回调堆栈帧map.putIfAbsent,则跟踪起来可能非常困难.
| 归档时间: |
|
| 查看次数: |
8844 次 |
| 最近记录: |