Ogn*_*yan 12 java multithreading aspectj thread-safety
语境:
我为游戏创建了一个小型(java)多线程服务器.尽管我尽最大努力遵循最佳实践,但事实证明,一些旨在从一个线程调用的方法是从2个或更多线程调用的.经过调试和分析后,我设法"修复"了我的设计,但我想知道:
问题:
是否有一个工具(或者如果不-是有可能(以及如何)开发),它允许您标记一些方法中包含注释@SingleThread或@ThreadCount(2)或@ThreadNameLike("my_fancy_thread_group*")用于计数/监视/日志访问这些方法,如:
@SingleThread - 检查此方法是否始终仅由线程访问@ThreadCount(2) - 完全由两个线程访问@ThreadNameLike - 仅由名称与模式匹配的线程访问我们的想法是对程序进行TEST运行,并至少获得违反注释条件的日志记录.
我当时认为可能AspectJ可以通过它的切入点来完成这项工作但后来我意识到类似于Dagger/Dagger2的方法会更好,即当你想测试你的服务器时你必须打开一个注释处理器(让我们假设它称为"SafetyFirst",它将生成包含监视代码的适配器(包装器?)类.然后,您将运行服务器,运行一些负载测试,然后检查日志是否存在违规(或在理想的世界中 - 获取报告文件).
我完全意识到这样的工具:
但至少它可以作为一个早期预警系统,清楚地宣传违反预期设计的行为.
我使用了类似的AspectJ加载时间编织测试来打算在我的包中打印所有函数调用.
加载时间编织的最佳方法是你不要像编译时间那样弄脏你的类.-javaagent:<path to aspectj lib>从运行命令中删除自定义的自定义lib类路径条目时.然后一切都消失了,清楚.
我做了一些更改,并实施了一个涵盖你问的@ThreadCount功能的测试.您需要下载并安装AspectJ.
请参阅代码段:
aspect Profile {
private static Map<String, AtomicInteger> counterMap = new HashMap<String, AtomicInteger>();
pointcut threadCountPc(test.ThreadCount tc) : execution(* test..*(..)) && @annotation(tc);
Object around(test.ThreadCount tc) : threadCountPc(tc) {
String signature = thisJoinPointStaticPart.getSignature().toString();
AtomicInteger counter = getCounter(signature);
int currentValue = counter.incrementAndGet();
if (currentValue >= tc.value()){
System.out.println("[Thread Name:" + Thread.currentThread().getName() +
"] Method Name:" + signature + ", threadCount:" + currentValue + " exceeds " + tc.value());
}
try{
return proceed(tc);
}finally{
counter.decrementAndGet();
}
}
private static AtomicInteger getCounter(String methodName){
AtomicInteger value = counterMap.get(methodName);
if (value == null){
synchronized (counterMap){
value = counterMap.get(methodName);
if (value == null){
value = new AtomicInteger(0);
counterMap.put(methodName, value);
}
}
}
return value;
}
}
Run Code Online (Sandbox Code Playgroud)
编译: "C:/aspectj1.8/bin/ajc.bat" profile_ft.aj -cp C:/aspectj1.8/lib/aspectjrt.jar;../test/. -1.6 -outxml -outjar profile_ft.jar
运行: java -javaagent:C:/aspectj1.8/lib/aspectjweaver.jar -cp aspectj/profile_ft.jar;test test.Test1