我正在编写一个使用多线程的项目的一部分,我试图找到检测代码中的线程错误的方法。 是否有一些现有的工具可以帮助我做到这一点?
例如 - 断言我的方法是由正确的线程调用的 要么 带有注释的某种静态检查,类似于@Nullable和@NotNull,用于检测我的代码何时从错误的线程调用方法。
虽然项目是多线程的,但几乎不需要同步,因为不同的线程不能访问相同的对象,它们有自己的实例。 一般来说,一次运行四个线程
这些类有时仅用于其中一个线程(例如用户输入轮询仅用于客户端),有时它们用于多个线程(例如,计算出的射弹移动同时在客户端和服务器上使用相同的代码减少感知滞后)。有好几次我从一个错误的线程中调用了一个方法,导致了微妙的,不可重复的错误以及非常严重的监视器屏幕损坏(来自我的拳头)
到目前为止我所想到的是这样的:
public void myMethodThatAssumesClientThreadOnly() {
assert checkThread(CLIENT);
// can now happily call other client-thread code without fear
}
但我更喜欢静态检查,类似于@Nullable
例如
@Thread(CLIENT)
void myClientMethod() {
//client-only stuff here
}
@Thread(SERVER)
void myServerMethod() {
//server-only stuff here
}
@Thread(CLIENT + SERVER)
void myClientAndMethod() {
myClientMethod(); // error- server thread might call client method
}
不幸的是,作为一个注释菜鸟,我不知道这是否容易或实际上非常困难。
任何指针?我无法想象我是第一个寻找类似事情的人。
TGG
答案 0 :(得分:0)
这将断言方法foobar()
由正确的线程调用...
SomeType foobar(...) {
assert(Thread.currentThread() == theCorrectThread);
...
}
...如果您在第一次foobar()
来电之前的代码中某处设置了
Thread theCorrectThread = new Thread(...);
但我更喜欢静态检查,类似于@Nullable
我自己对注释知之甚少。我知道它们可以用于将元信息附加到已编译的类,我知道程序可以通过调用Class
对象的方法在运行时获取该信息,但是如果注释可以有任何方式可以定义编译时行为,这超出了我的范围。
无论如何可能是一个有争议的问题。当编译器处理.java文件时,它无法告诉哪些线程可能执行它包含的代码。
答案 1 :(得分:0)
Checker Framework可以创建编译时静态检查程序,以验证程序的正确性。它的GUI Effect Checker与你想要的类似。以下是its manual的简略摘录:
最常见的GUI相关错误之一是无效的UI更新或无效的线程访问:直接从后台线程访问UI。
如果后台线程访问诸如JPanel之类的UI元素(通过调用JPanel方法或读取/写入JPanel字段),GUI框架会引发一个终止程序的异常。
程序员很难记住可以在哪个线程上调用哪些方法。 GUI Effect Checker解决了这个问题。程序员注释每个方法以指示是否:
- 它不访问任何UI元素(并且可以在任何线程上运行)。
- 它可以访问UI元素(并且必须在UI线程上运行)。
GUI效果检查器静态强制仅从正确的线程调用UI方法。
GUI效果检查器已调整为检测和防止GUI线程错误,而您则担心客户端 - 服务器线程错误。但是,原则是相同的,您应该能够通过相对较少的更改来调整GUI效果检查器。
有paper使用GUI效果检查器讨论案例研究。
另一种方法是调整bug finder以在多线程应用程序中查找错误。与GUI效果检查器不同,它不提供保证没有线程错误。但是,它在实践中很有效,并且它不要求您在程序中编写任何注释。
最后,Checker Framework还包含一个Lock Checker,可确保正确同步。这有助于防止并发错误,尽管它与您对线程安全的主要担忧是正交的。