質問

ConcurrentHashMapの奇妙な問題に遭遇しました。ここで、2つのスレッドはput()を呼び出してから、メソッドUnsafe.park()の中で永久に待機します。外部から、ConcurrentHashMapの中のデッドロックのように見えます。

これがこれまでに起こるのを見ました。

誰かがこれらの症状を引き起こす可能性があるものについて考えてもらえますか?

edit :関連スレッドのスレッドダンプはここにあります:

"[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]
.

役に立ちましたか?

解決

あなたが望む答えではありませんが、これはJVMのバグです。

を参照してください

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

他のヒント

私はこれがあなたの訴訟の起こっているものであるとは思わないが、ConcurrentHashMapの単一のインスタンスを持つデッドロックを書くことが可能であり、1つのスレッドだけを必要とします!かなりの間あなたを立ち往生していました。

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;
});
.

今すぐスタックで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.computemap.putIfAbsentへの呼び出しの間にイベントコールバックの百のスタックフレームがある場合は、トラッキングが非常に困難になる可能性があります。

パッケージの安全なネイティブで、実装はプラットフォームによって異なります。

第3スレッドの突然終了(プラットフォームレベルでは、エクセピオンは問題ではありません)このような状況を引き起こす可能性がある - ロックの状態が壊れている可能性がある、他の2つのスレッドは無効になり、誰かがUnsafe.Unparkを呼び出すのを待っています()(そしてそれは起こりません)。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top