ThreadPoolExecutor中的死锁

Vit*_*aly 13 java concurrency

当所有线程都在func 中等待时,遇到ThreadPoolExecutor停在execute(Runnable)函数中的情况,workQueue为空.ThreadPoolgetTask

有人有什么想法吗?

ThreadPoolExecutor与创建ArrayBlockingQueue,和corePoolSize == maximumPoolSize = 4

[编辑]更准确地说,线程在ThreadPoolExecutor.exec(Runnable command)func中被阻止.它有执行任务,但没有执行.

[Edit2]执行程序被阻塞在工作队列(ArrayBlockingQueue)内的某处.

[Edit3] callstack:

thread = front_end(224)
at sun.misc.Unsafe.park(Native methord)
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.ArrayBlockingQueue.offer(ArrayBlockingQueue.java:224)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:653)
at net.listenThread.WorkersPool.execute(WorkersPool.java:45)
Run Code Online (Sandbox Code Playgroud)

同时workQueue为空(使用远程调试检查)

[Edit4]代码使用ThreadPoolExecutor:

public WorkersPool(int size) {
  pool = new ThreadPoolExecutor(size, size, IDLE_WORKER_THREAD_TIMEOUT, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(WORK_QUEUE_CAPACITY),
      new ThreadFactory() {
        @NotNull
        private final AtomicInteger threadsCount = new AtomicInteger(0);

        @NotNull
        public Thread newThread(@NotNull Runnable r) {
          final Thread thread = new Thread(r);
          thread.setName("net_worker_" + threadsCount.incrementAndGet());
          return thread;
        }
      },

      new RejectedExecutionHandler() {
        public void rejectedExecution(@Nullable Runnable r, @Nullable ThreadPoolExecutor executor) {
          Verify.warning("new task " + r + " is discarded");
        }
      });
  }

  public void execute(@NotNull Runnable task) {
    pool.execute(task);
  }

  public void stopWorkers() throws WorkersTerminationFailedException {
    pool.shutdownNow();
    try {
      pool.awaitTermination(THREAD_TERMINATION_WAIT_TIME, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
      throw new WorkersTerminationFailedException("Workers-pool termination failed", e);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

nic*_*ild 7

听起来这是一个JVM早于6u21的错误.编译的本机代码中存在一些(可能是所有)操作系统的问题.

从链接:

该错误是由于各种Parker :: park()路径中丢失的内存障碍导致丢失和挂起.(请注意,内置同步使用的PlatformEvent :: park不容易受到此问题的影响).-XX:+ UseMembar构成一个解决方法,因为状态转换逻辑中的membar屏障隐藏了Parker ::中的问题.(也就是说,使用-UseMembar机制没什么问题,但是+ UseMembar隐藏了Parker::)的bug.这是在JDK 5.0中添加java.util.concurrent引入的第一天错误.我开发了一种简单的C模式的故障,它似乎更有可能在现代AMD和Nehalem平台上体现,可能是因为更长的存储缓冲区需要更长时间才能耗尽.我为Doug Lea提供了Parker :: park的初步修复,似乎消除了这个bug.我将把这个修复程序提供给运行时.(我还将通过额外的测试用例和更长的解释来增加CR).这可能是后端口的良好候选者.

链接:JVM Bug

可以使用变通方法,但最好只获取最新的Java副本.


akf*_*akf 2

ThreadPoolExecutor我在s的代码中没有看到任何锁定execute(Runnable)。唯一的变量是workQueue. BlockingQueue你给你提供了什么样的ThreadPoolExecutor

关于死锁的话题:

<ctrl><break>您可以通过检查Windows 或UNIX 系统上提供的完整线程转储来确认这是死锁kill -QUIT

获得该数据后,您可以检查线程。以下是Sun 的有关检查线程转储的文章的相关摘录(建议阅读) :

对于挂起、死锁或冻结的程序:如果您认为程序挂起,请生成堆栈跟踪并检查处于 MW 或 CW 状态的线程。如果程序死锁,那么某些系统线程可能会显示为当前线程,因为 JVM 无事可做。

简单地说:如果您在 IDE 中运行,您能否确保这些方法中没有启用断点。