java deadlock降低性能

时间:2016-06-20 12:16:09

标签: java tomcat deadlock logback

我们使用java7和tomcat7运行Web应用程序。在我们的应用程序中,性能非常突然。平均响应时间加倍,在高峰时段问题甚至变得更糟。

我们打印出一个线程转储,发现一个线程坐在那里等待一个条件。我们做了几次线程转储,这个线程的状态从未改变过。

"logback-66215" daemon prio=10 tid=0x00007f86f4115800 nid=0x3758 waiting on condition [0x00007f868d817000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00007f8ddf241fa8> (a java.util.concurrent.SynchronousQueue$TransferStack)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
        at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:458)
        at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359)
        at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:925)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)

在线程转储中找不到此线程中对0x00007f868d817000和0x00007f868d817000的引用。

重新启动tomcat后,线程消失了,性能就像它应该的那样。

我们在拥有12个核心的服务器上运行它。我们监控CPU使用率但没有看到峰值。当处于峰值负载时,由于大约500个请求/秒,CPU使用率确实上升到800%,但没有进一步增加到1200%(这是最大值)。当它达到800%时它停止增加,然后性能问题当然非常糟糕。

我对线程,CPU,中断的内部结构了解不足,无法完全理解这种情况。我真的想在更深层次上理解这个问题。

现在我的问题:有人可以解释一下,为什么像这样的僵局会导致这么多麻烦?为什么它没有显示CPU使用率,所以我们看到一个满载的CPU?或者只是上下文切换的问题?

1 个答案:

答案 0 :(得分:0)

如果我错了,请纠正我,但基于上面的线程转储,以及SynchronousQueue的存在,我猜你正在使用CachedThreadPoolExecutor(Executors.newCachedThreadPool())来执行某些任务。 / p>

因此转储将是其中一个缓存线程的转储,只需等待作业在线程池中入队。这里没有错,这不是死锁 - 无论如何,真正的死锁将在线程转储中明确地说明。

对于CPU消耗,处于WAITING状态的线程不消耗任何CPU周期 - 它甚至没有被安排执行。

那么,您的性能问题来自哪里?

很难说,但如果我是你,我会避免使用CachedThreadPool,因为它会努力创建执行作业所需的多个线程,即使它意味着吃掉所有服务器的内存(每个线程都保留了)其堆栈的内存,至少为100k)和CPU(如果有太多的线程需要管理,你的调度程序会变得疯狂)。

您可能希望手动配置ThreadPoolExecutor(而不是使用Executors.new*工厂),以便能够选择最大线程数,队列大小和类型,以及大的情况下的退避策略大部分工作即将到来。