java死锁降低性能

标签 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?还是只是上下文切换的问题?

最佳答案

如果我错了请纠正我,但是根据上面的线程转储,以及 SynchronousQueue 的存在,我猜你正在使用 CachedThreadPoolExecutor (Executors.newCachedThreadPool() ) 来执行一些任务。

因此转储将是其中一个缓存线程的转储,只是等待作业在线程池中排队。这里没什么问题,这不是死锁——真正的死锁无论如何都会在线程转储中明确说明。

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

那么,您的性能问题从何而来?

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

您可能需要手动配置 ThreadPoolExecutor(而不是使用 Executors.new* 工厂),以便能够选择最大线程数、队列大小和类型以及退避大量工作岗位到来时的策略。

关于java死锁降低性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37922376/

相关文章:

java - 使用 ListView 滚动布局 android

java - 给定一个全 0 的二进制字符串,将其隐藏到目标字符串中

tomcat - Windows 10 上的 Spring STS Spring Tools Suite 端口问题 Tomcat

tomcat - 远程部署到tomcat

c - 练习程序不按预期制造死锁

multithreading - 如何确保锁定顺序以避免死锁?

java - 相机对象总是返回 null

java - 当部署到独立的 tomcat 而不是 Eclipse 的 Tomcat 时,我基于 Spring 的 Restful web 服务给出 404

Java,线程死锁?

java - 在 Eclipse 中为 http 请求使用代理