synchronized
에서 ReadWriteLock
으로 전환하는 것이 좋습니다. 그것을하기 전에, 나는 그것이 가치가 있는지 확인하고 싶습니다.특정 모니터에서 스레드 경합 측정
ThreadMXBean
및 ThreadInfo
은 전체 스레드 차단 횟수 및 시간에 대한 정보를 제공합니다. 이러한 블록은 다중 모니터로 인해 발생할 수 있습니다. 특정 모니터 객체가 주어진 경우 블록 통계를 측정하는 방법이 있습니까?
synchronized
에서 ReadWriteLock
으로 전환하는 것이 좋습니다. 그것을하기 전에, 나는 그것이 가치가 있는지 확인하고 싶습니다.특정 모니터에서 스레드 경합 측정
ThreadMXBean
및 ThreadInfo
은 전체 스레드 차단 횟수 및 시간에 대한 정보를 제공합니다. 이러한 블록은 다중 모니터로 인해 발생할 수 있습니다. 특정 모니터 객체가 주어진 경우 블록 통계를 측정하는 방법이 있습니까?
ReentrantReadWriteLock의 내부 커널 - 유형이 AbstractQueuedSynchronizer (AQS) 인 개인 필드 'sync'. AQS - Doug Lea의 가장 훌륭한 '싱크로 나이저'중 하나입니다. 경합 스레드의 단일 링크 목록을 포함합니다. 표시된 모든 스레드는 '독점'또는 '공유'입니다. 자세한 내용은 "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