からReadWriteLock
に切り替えることを検討しています。それを行う前に、それがその価値があるかどうかチェックしたいと思います。特定のモニタでスレッドの競合を測定する
ThreadMXBean
およびThreadInfo
は、全体的なスレッドブロックカウントおよび時間に関する情報を提供します。これらのブロックは、複数のモニターによって発生する可能性があります。特定のモニターオブジェクトを指定してブロック統計を測定する方法はありますか?
からReadWriteLock
に切り替えることを検討しています。それを行う前に、それがその価値があるかどうかチェックしたいと思います。特定のモニタでスレッドの競合を測定する
ThreadMXBean
およびThreadInfo
は、全体的なスレッドブロックカウントおよび時間に関する情報を提供します。これらのブロックは、複数のモニターによって発生する可能性があります。特定のモニターオブジェクトを指定してブロック統計を測定する方法はありますか?
ReentrantReadWriteLockの内部カーネル - タイプAbstractQueuedSynchronizer(AQS)のプライベートフィールド 'sync'。 AQS - Doug Leaの最もシンクロナイザーの1つ。これには、競合スレッドの単一リンクリストが含まれています。マークされたすべてのスレッドは「排他的」または「共有」です。 詳細については"The java.util.concurrent Synchronizer Framework"をお読みください。
ブロックされたスレッドキューを定期的に調べて(100秒単位で)統計情報を収集できます。
import java.lang.reflect.Field;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class App {
static final AtomicInteger freeTime = new AtomicInteger(0);
static final AtomicInteger fullTime = new AtomicInteger(0);
static final AtomicInteger readersLength = new AtomicInteger(0);
static final AtomicInteger writersLength = new AtomicInteger(0);
public static float contended() {
return fullTime.get()/(fullTime.get() + freeTime.get());
}
public static float uncontended() {
return freeTime.get()/(fullTime.get() + freeTime.get());
}
public static float meanReadersQueue() {
return readersLength.get()/fullTime.get();
}
public static float meanWritersQueue() {
return writersLength.get()/fullTime.get();
}
public static void main(String[] args) throws Exception {
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
AbstractQueuedSynchronizer sync =
useReflection(lock, "sync", AbstractQueuedSynchronizer.class);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> {
int queueLength = sync.getQueueLength();
if (queueLength == 0) {
freeTime.incrementAndGet();
} else {
fullTime.incrementAndGet();
int readersCount = sync.getSharedQueuedThreads().size();
readersLength.addAndGet(readersCount);
int writersCount = sync.getExclusiveQueuedThreads().size();
writersLength.addAndGet(writersCount);
}
}, 0, 10, TimeUnit.MILLISECONDS);
}
private static <T> T useReflection(Object from, String name, Class<T> to) throws Exception {
Field f = from.getClass().getDeclaredField(name);
f.setAccessible(true);
return (T) f.get(from);
}
}
はい、JVMTIを使用することができます。
あなたが何を必要としているが、イベントのペアを扱うネイティブエージェントを書くことです:
両方のイベントは、モニタとモニタオブジェクト自体を取得するスレッドに対応jthread
とjobject
引数を受け入れます。
Here is競合プロファイラエージェントのサンプルコードです。
ありがとう、私はjconsoleとvisualvmだけに精通していて、ロックの競合情報を提供していません。 jmcは私が欲しいもののように見えます。あなたはあなたの答えを以下に投稿できますか? – damluar