监视Java应用程序上的锁争用
我试图创建一个小的基准(在Groovy中),显示几个同步方法的高线程争用。 监控自愿上下文切换时应该出现高争用,而在Linux中,这可以通过“pidstat”来实现。
该计划如下:
class Res { private int n; synchronized public void inc() { n++; def foo = [] for (int i = 0; i < 1000; ++i) foo << "hello" } synchronized public int getN() { return n; } } while (true) { Res res = new Res() int N = 100000 for (int i = 0; i < N; ++i) { new Thread({ res.inc() if (res.getN() == N) { println "ok" } }).start() } while (res.getN() < N) { } println "=========================" }
但命令
pidstat -w -I -p 26848 5
在自愿上下文切换列上打印0。 该程序创建100000个线程,同时访问同步方法。 我无法相信,有了这样的工作量,就不会发生上下文切换。
我的基准测试有什么问题?
您的命令仅显示主线程的统计信息,不计算子PID。
Hotspot JVM有内部同步计数器,但需要一些魔法来解锁它们:
- 运行
jconsole.exe -J-Djconsole.showUnsupported
并连接到您的JVM。 - 从主菜单中选择Connection – > Hotspot MBeans – > Create 。
- 在MBeans选项卡上打开sun.management.HotspotRuntime 。
- 你会在InternalRuntimeCounters属性下找到一堆计数器:
- sun.rt._sync_ContendedLockAttempts
- sun.rt._sync_Parks
- sun.rt._sync_Notifications
- sun.rt._sync_Inflations
等等