Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java中何处查找同步争用证据?_Java_Performance_Multithreading_Synchronization_Contention - Fatal编程技术网

在java中何处查找同步争用证据?

在java中何处查找同步争用证据?,java,performance,multithreading,synchronization,contention,Java,Performance,Multithreading,Synchronization,Contention,当我们的Tomcat web应用程序被几百个用户使用时,它感觉很慢。服务器在一家托管公司,它们的报告没有显示任何bandwith或cpu工作负载问题,因此我怀疑速度变慢的原因可能是因为我们封装在同步调用下的一些遗留代码存在争用,因为这是一条更容易的路径 我在开发环境中做了一些人工测试,用ThreadLocal解决方案更改了同步调用,速度变得更快,但我知道我的老板会要求我提供一些证据,证明它在生产中也会更快 我怎样才能确定我的应用程序中是否存在线程争用问题?我可以像这样在同步调用中添加日志记录 /

当我们的Tomcat web应用程序被几百个用户使用时,它感觉很慢。服务器在一家托管公司,它们的报告没有显示任何bandwith或cpu工作负载问题,因此我怀疑速度变慢的原因可能是因为我们封装在同步调用下的一些遗留代码存在争用,因为这是一条更容易的路径

我在开发环境中做了一些人工测试,用ThreadLocal解决方案更改了同步调用,速度变得更快,但我知道我的老板会要求我提供一些证据,证明它在生产中也会更快


我怎样才能确定我的应用程序中是否存在线程争用问题?

我可以像这样在同步调用中添加日志记录

//...
long t0 = System.currentTimeMillis();
synchronized(lockObj){
    logger.info("T sync :" + (t0 - System.currentTimeMillis()));
    //...
}

但这感觉既便宜又脏

如果您有一个您认为更快的修改版本,请使用一些负载测试仪(例如)测试这两个版本。如果有显著的差异,你会有结果来证明这一点。

你可以支配一堆人,以及其他可能需要花钱的人,比如。您应该使用现有代码和增强代码运行测试。使用TraceLoad的工作一般应该减少争用,但是在开始优化之前,最好还是做基准测试。p> 另一个非常简单的测试可以在不设置任何分析器的情况下完成,即在应用程序运行缓慢时执行一些线程转储(ctrl-break或kill-QUIT)。在短时间内发现几个线程在类似或相同的监视器上等待,可能会非常清楚地指出慢点。您可以使用Java线程转储分析器来帮助您梳理线程转储


同样,在开始优化之前做这项工作是一个好主意。这是因为,虽然可能有一些明显的地方,优化可以产生差异,但实际用户行为可能触发开发人员不考虑的路径,而这些路径可能是真正的问题区域。

< P>您的分析听起来合理。您能否将visualvm(在JDK中)附加到流程中,以便查看时间花在哪里?

我认为,最新Java 6 JDK附带的visualvm工具视图将能够为您的理论提供坚实的证据(或相反的证据)。它为每个线程显示一个饼图,显示它在运行、睡眠、等待和在监视器中花费的时间。最后一个(以红色显示)是您感兴趣的内容:

jstack PID

将打印一个进程id为PID的JVM状态列表,以及有关线程状态的信息

样本输出(摘录):

“AWT-XAWT”守护程序prio=10 tid=0x0000000000e5f800 nid=0x476d可运行[0x00007f1a756160000..0x00007f1a75616bf0]
java.lang.Thread.State:可运行
位于sun.awt.X11.XToolkit.waitForEvents(本机方法)
位于sun.awt.X11.XToolkit.run(XToolkit.java:543)
位于sun.awt.X11.XToolkit.run(XToolkit.java:518)
运行(Thread.java:636)
对象中的“Java2D处理器”守护程序prio=10 tid=0x0000000000d8b800 nid=0x476c.wait()[0x00007f1a759df000..0x00007f1a759dfc70]
java.lang.Thread.State:正在等待(在对象监视器上)
在java.lang.Object.wait(本机方法)
-等待(java.lang.ref.ReferenceQueue$Lock)
位于java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:133)
-锁定(java.lang.ref.ReferenceQueue$Lock)
位于java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:149)
运行(Disposer.java:143)
运行(Thread.java:636)

我还将尝试隔离争用下的资源。e、 g.如果旧库锁定以同步对数据库的写入,您可能会最小化写入。

谢谢,但我们没有一个与生产相同的集成环境来运行此类测试。在development中运行JMeter测试将与我已经完成的测试相同。我以前使用Eclipse TPTP和Netbeans分析过应用程序的一部分,但分析整个应用程序会变得非常缓慢,因此我从未尝试在进行负载测试时进行分析,因为如果它不崩溃,将需要数小时。是的,试图将一个大型应用程序置于探查器之下可能是一项艰巨的工作。Michael Borgwardt建议的工具看起来很有前途。如果您想获得重要的数字,应该使用nanoTime(),而不是currentTimeMillis()。请注意,这种日志记录>>可能会
"AWT-XAWT" daemon prio=10 tid=0x0000000000e5f800 nid=0x476d runnable [0x00007f1a75616000..0x00007f1a75616bf0]
   java.lang.Thread.State: RUNNABLE
    at sun.awt.X11.XToolkit.waitForEvents(Native Method)
    at sun.awt.X11.XToolkit.run(XToolkit.java:543)
    at sun.awt.X11.XToolkit.run(XToolkit.java:518)
    at java.lang.Thread.run(Thread.java:636)

"Java2D Disposer" daemon prio=10 tid=0x0000000000d8b800 nid=0x476c in Object.wait() [0x00007f1a759df000..0x00007f1a759dfc70]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x00007f1a82e2c3f8> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:133)
    - locked <0x00007f1a82e2c3f8> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:149)
    at sun.java2d.Disposer.run(Disposer.java:143)
    at java.lang.Thread.run(Thread.java:636)