繁体   English   中英

“ConcurrentHashMap”可能会挂起吗?

[英]is it possible for `ConcurrentHashMap` to hang?

首先,我将总结到目前为止我发现的内容。

  • 这个答案表明,更改ConcurrentHashMap的构造函数的concurrencyLevel参数可能会有所帮助。 我试过了,我的代码仍然被绞死了。
  • 这里的答案表明它可能是一个运行时错误。

我正在尝试做什么:

  • 我有10个工作线程与主线程一起运行。 工作线程必须处理许多数组以查找数组中max元素的索引(如果有多个最大值,则将使用第一个出现的值)。 在这些“许多阵列”中,其中一些可能是重复的,所以我试图避免那些完整的阵列扫描来加速程序。
  • 控制器类包含一个ConcurrentHashMap ,它将数组的哈希值映射到相应的max-element索引。
  • 在尝试通过执行完整阵列扫描来计算索引之前,工作线程将首先向控制器类询问映射索引。 在后一种情况下,新计算的索引将被放入地图中。
  • 主线程不访问哈希映射。

发生了什么:

  • 在对getMaxIndex()进行70,000~130,000次调用后,我的代码将挂起。 这个计数是通过将一个日志字符串放入getMaxIndex()因此它可能不完全准确。
  • 我的CPU使用率将逐渐上升约6秒,然后在达到~100%达到峰值后下降到~10%。 我还有很多未使用的内存。 (这看起来像僵局吗?)
  • 如果代码不使用map,它就可以正常工作(参见下面的getMaxIndex()版本2)。
  • 我试图将synchronized添加到getMaxIndex()的签名并使用常规的HashMap ,这也没有用。
  • 我也试过使用不同的initialCapacity值(例如50,000和100,000)。 不工作。

这是我的代码:

// in the controller class
int getMaxIndex(@NotNull double[] arr) {
    int hash = Arrays.hashCode(arr);

    if(maxIndices.containsKey(hash)) {
        return maxIndices.get(hash);
    } else {
        int maxIndex =
            IntStream.range(0, arr.length)
                .reduce((a, b) -> arr[a] < arr[b] ? b : a)
                .orElse(-1); // -1 to let program crash

        maxIndices.put(hash, maxIndex);
        return maxIndex;
    }
}

工作线程将像这样调用getMaxIndex()return remaining[controller.getMaxIndex(arr)]; remaining的只是另一个int数组。

getMaxIndex() v2:

int getMaxIndex(@NotNull double[] arr) {
    return IntStream.range(0, arr.length)
        .reduce((a, b) -> arr[a] < arr[b] ? b : a)
        .orElse(-1); // -1 to let program crash
}

JVM信息以防万一:

java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)

编辑 :堆栈转储; 我使用Phaser来同步工作线程,因此其中一些似乎正在等待相位器,但是pool-1-thread-2pool-1-thread-10pool-1-thread-11pool-1-thread-12似乎没有等待相位器。

Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.151-b12 mixed mode):

"Attach Listener" #23 daemon prio=9 os_prio=0 tid=0x00007f0c54001000 nid=0x4da2 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"pool-1-thread-13" #22 prio=5 os_prio=0 tid=0x00007f0c8c2cb800 nid=0x4d5e waiting on condition [0x00007f0c4eddd000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x000000076e792f40> (a java.util.concurrent.Phaser$QNode)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.Phaser$QNode.block(Phaser.java:1140)
    at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3323)
    at java.util.concurrent.Phaser.internalAwaitAdvance(Phaser.java:1067)
    at java.util.concurrent.Phaser.arriveAndAwaitAdvance(Phaser.java:690)
    at Ant.call(Ant.java:77)
    at Ant.call(Ant.java:10)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

"pool-1-thread-12" #21 prio=5 os_prio=0 tid=0x00007f0c8c2ca000 nid=0x4d5d waiting on condition [0x00007f0c4eede000]
   java.lang.Thread.State: TIMED_WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x0000000775518738> (a java.util.concurrent.SynchronousQueue$TransferStack)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
    at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
    at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
    at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:941)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1073)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

"pool-1-thread-11" #20 prio=5 os_prio=0 tid=0x00007f0c8c2c8000 nid=0x4d5c waiting on condition [0x00007f0c4efdf000]
   java.lang.Thread.State: TIMED_WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x0000000775518738> (a java.util.concurrent.SynchronousQueue$TransferStack)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
    at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
    at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
    at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:941)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1073)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

"pool-1-thread-10" #19 prio=5 os_prio=0 tid=0x00007f0c8c2c6000 nid=0x4d5b waiting on condition [0x00007f0c4f0e0000]
   java.lang.Thread.State: TIMED_WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x0000000775518738> (a java.util.concurrent.SynchronousQueue$TransferStack)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
    at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
    at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
    at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:941)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1073)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

"pool-1-thread-9" #18 prio=5 os_prio=0 tid=0x00007f0c8c2c4800 nid=0x4d5a waiting on condition [0x00007f0c4f1e1000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x000000076e7c74f8> (a java.util.concurrent.Phaser$QNode)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.Phaser$QNode.block(Phaser.java:1140)
    at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3323)
    at java.util.concurrent.Phaser.internalAwaitAdvance(Phaser.java:1067)
    at java.util.concurrent.Phaser.arriveAndAwaitAdvance(Phaser.java:690)
    at Ant.call(Ant.java:77)
    at Ant.call(Ant.java:10)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

"pool-1-thread-8" #17 prio=5 os_prio=0 tid=0x00007f0c8c2c2800 nid=0x4d59 waiting on condition [0x00007f0c4f2e2000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x000000076e64fb78> (a java.util.concurrent.Phaser$QNode)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.Phaser$QNode.block(Phaser.java:1140)
    at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3323)
    at java.util.concurrent.Phaser.internalAwaitAdvance(Phaser.java:1067)
    at java.util.concurrent.Phaser.arriveAndAwaitAdvance(Phaser.java:690)
    at Ant.call(Ant.java:77)
    at Ant.call(Ant.java:10)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

"pool-1-thread-7" #16 prio=5 os_prio=0 tid=0x00007f0c8c2c1000 nid=0x4d58 waiting on condition [0x00007f0c4f3e3000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x000000076e8b44c8> (a java.util.concurrent.Phaser$QNode)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.Phaser$QNode.block(Phaser.java:1140)
    at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3323)
    at java.util.concurrent.Phaser.internalAwaitAdvance(Phaser.java:1067)
    at java.util.concurrent.Phaser.arriveAndAwaitAdvance(Phaser.java:690)
    at Ant.call(Ant.java:77)
    at Ant.call(Ant.java:10)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

"pool-1-thread-6" #15 prio=5 os_prio=0 tid=0x00007f0c8c2bf800 nid=0x4d57 waiting on condition [0x00007f0c4f4e4000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x000000076e5b4500> (a java.util.concurrent.Phaser$QNode)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.Phaser$QNode.block(Phaser.java:1140)
    at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3323)
    at java.util.concurrent.Phaser.internalAwaitAdvance(Phaser.java:1067)
    at java.util.concurrent.Phaser.arriveAndAwaitAdvance(Phaser.java:690)
    at Ant.call(Ant.java:77)
    at Ant.call(Ant.java:10)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

"pool-1-thread-5" #14 prio=5 os_prio=0 tid=0x00007f0c8c2bd800 nid=0x4d56 waiting on condition [0x00007f0c4f5e5000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x000000076e836958> (a java.util.concurrent.Phaser$QNode)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.Phaser$QNode.block(Phaser.java:1140)
    at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3323)
    at java.util.concurrent.Phaser.internalAwaitAdvance(Phaser.java:1067)
    at java.util.concurrent.Phaser.arriveAndAwaitAdvance(Phaser.java:690)
    at Ant.call(Ant.java:77)
    at Ant.call(Ant.java:10)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

"pool-1-thread-4" #13 prio=5 os_prio=0 tid=0x00007f0c8c2bc000 nid=0x4d55 waiting on condition [0x00007f0c4f6e6000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x000000076e4f4cf0> (a java.util.concurrent.Phaser$QNode)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.Phaser$QNode.block(Phaser.java:1140)
    at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3323)
    at java.util.concurrent.Phaser.internalAwaitAdvance(Phaser.java:1067)
    at java.util.concurrent.Phaser.arriveAndAwaitAdvance(Phaser.java:690)
    at Ant.call(Ant.java:77)
    at Ant.call(Ant.java:10)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

"pool-1-thread-3" #12 prio=5 os_prio=0 tid=0x00007f0c8c2ba000 nid=0x4d54 waiting on condition [0x00007f0c4f7e7000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x000000076e40abb8> (a java.util.concurrent.Phaser$QNode)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.Phaser$QNode.block(Phaser.java:1140)
    at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3323)
    at java.util.concurrent.Phaser.internalAwaitAdvance(Phaser.java:1067)
    at java.util.concurrent.Phaser.arriveAndAwaitAdvance(Phaser.java:690)
    at Ant.call(Ant.java:77)
    at Ant.call(Ant.java:10)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

"pool-1-thread-2" #11 prio=5 os_prio=0 tid=0x00007f0c8c2b8800 nid=0x4d53 waiting on condition [0x00007f0c4f8e8000]
   java.lang.Thread.State: TIMED_WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x0000000775518738> (a java.util.concurrent.SynchronousQueue$TransferStack)
    at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
    at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
    at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362)
    at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:941)
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1073)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

"pool-1-thread-1" #10 prio=5 os_prio=0 tid=0x00007f0c8c2b5800 nid=0x4d52 waiting on condition [0x00007f0c4f9e9000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x000000076e486ab0> (a java.util.concurrent.Phaser$QNode)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.Phaser$QNode.block(Phaser.java:1140)
    at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3323)
    at java.util.concurrent.Phaser.internalAwaitAdvance(Phaser.java:1067)
    at java.util.concurrent.Phaser.arriveAndAwaitAdvance(Phaser.java:690)
    at Ant.call(Ant.java:77)
    at Ant.call(Ant.java:10)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00007f0c8c200800 nid=0x4d50 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread2" #8 daemon prio=9 os_prio=0 tid=0x00007f0c8c1fd800 nid=0x4d4f waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #7 daemon prio=9 os_prio=0 tid=0x00007f0c8c1f8800 nid=0x4d4e waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #6 daemon prio=9 os_prio=0 tid=0x00007f0c8c1f7800 nid=0x4d4d waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #5 daemon prio=5 os_prio=0 tid=0x00007f0c8c1fb000 nid=0x4d4c runnable [0x00007f0c781b4000]
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:171)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    - locked <0x000000077550ecb0> (a java.io.InputStreamReader)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.BufferedReader.fill(BufferedReader.java:161)
    at java.io.BufferedReader.readLine(BufferedReader.java:324)
    - locked <0x000000077550ecb0> (a java.io.InputStreamReader)
    at java.io.BufferedReader.readLine(BufferedReader.java:389)
    at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007f0c8c181000 nid=0x4d49 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007f0c8c14d800 nid=0x4d42 in Object.wait() [0x00007f0c78564000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x0000000775500d08> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
    - locked <0x0000000775500d08> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007f0c8c149000 nid=0x4d41 in Object.wait() [0x00007f0c78665000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x0000000775500d48> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:502)
    at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
    - locked <0x0000000775500d48> (a java.lang.ref.Reference$Lock)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"main" #1 prio=5 os_prio=0 tid=0x00007f0c8c00c800 nid=0x4d35 waiting on condition [0x00007f0c91f77000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x000000076dd5e268> (a java.util.concurrent.FutureTask)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429)
    at java.util.concurrent.FutureTask.get(FutureTask.java:191)
    at java.util.concurrent.AbstractExecutorService.invokeAll(AbstractExecutorService.java:244)
    at ConcurrentACS.loop(ConcurrentACS.java:138)
    at ConcurrentACS.compute(ConcurrentACS.java:165)
    at ConcurrentACS.main(ConcurrentACS.java:192)

"VM Thread" os_prio=0 tid=0x00007f0c8c141800 nid=0x4d3f runnable 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f0c8c022000 nid=0x4d37 runnable 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f0c8c024000 nid=0x4d38 runnable 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007f0c8c025800 nid=0x4d39 runnable 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007f0c8c027800 nid=0x4d3a runnable 

"VM Periodic Task Thread" os_prio=0 tid=0x00007f0c8c205800 nid=0x4d51 waiting on condition 

JNI global references: 272

ConcurrentHashMap可以挂起吗?

简短的回答是不,如果“挂起”你的意思是某种程序循环或死锁。 如果你暗示你在该代码中发现了一个竞争条件(bug)会导致它在正常的JVM和系统执行期间挂起,那么我非常怀疑它。

我怀疑还有其他事情发生,只是因为你在悬挂的版本中使用CHM并不意味着该类有一个bug。 我会使用堆栈转储或分析器来显示代码在CHM行上被锁定,然后我就会抛出任何责任。

是否有可能每秒多次调用CHM,以便程序的性能因此受到影响? 当然。 但它不会因为卡住或陷入僵局而陷入困境。

我的CPU使用率将逐渐上升约6秒,然后在达到~100%达到峰值后下降到~10%。 我还有很多未使用的内存。 (这看起来像僵局吗?)

您现在发布的堆栈跟踪显示CHM代码中没有锁定任何线程,因此它看起来不是问题。 您正在讨论的性能曲线似乎正在发生,因为您使用的fork / join线程池最初启动X线程,但随后其中一些完成了他们的任务并退出。 这是可以预料的。 它与CHM无关。

 if(maxIndices.containsKey(hash)) { return maxIndices.get(hash); 

快速评论一下。 此代码对CHM进行2次调用,而不是像:

Integer maxIndex = maxIndices.get(hash);
if (maxIndex != null) {
   return maxIndex;
}
...

但这只是低效率,不会导致错误。 此外,重要的是要认识到代码中的竞争条件意味着多个线程可能会为索引获取null并计算索引值。 但这也不是导致“挂起”的错误。

第一个版本不是线程安全的,因为check-than-act序列不是原子序列。 尝试使用此实现:

  private final Map<Integer, Integer> maxIndices = new ConcurrentHashMap<>();

  int getMaxIndex(final double[] arr) {
    // make sure the content of the arr can't be modified concurrently
    // otherwise create a copy of the array in this method
    int hash = Arrays.hashCode(arr);
    return maxIndices.computeIfAbsent(hash,
        key -> IntStream.range(0, arr.length).reduce((a, b) -> arr[a] < arr[b] ? b : a).orElse(-1));
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM