线程正确性的断言或注释
Assertions or Annotations for thread correctness
我正在编写一个使用多线程的项目的一部分,我正在尝试寻找检测代码中线程错误的方法。
是否有一些现有的工具可以帮助我做到这一点?
例如-
断言我的方法正在被正确的线程调用
要么
某种带有注释的静态检查,类似于@Nullable 和@NotNull,以检测我的代码何时从错误的线程调用方法。
虽然项目是多线程的,但几乎不需要同步,因为不同的线程不会访问相同的对象,它们有自己的实例。
从广义上讲,一次有四个线程运行
- 服务器线程=维护游戏状态一个或多个
客户
- 客户端线程 = 处理用户输入,维护本地
copy/cache 用于渲染的服务器数据
- NetworkMessage 线程 = 处理 incoming/outgoing 条消息
服务器和客户端之间
- 渲染线程=将本地数据处理为渲染信息
显卡
类 有时仅用于一个线程(例如用户输入轮询仅客户端),有时它们用于多个线程(例如弹丸的计算运动使用相同的代码同时在客户端和服务器上以减少感知延迟)。有好几次我从错误的线程调用方法,导致微妙且不可重复的错误和非常严重的显示器屏幕损坏(来自我的拳头)
目前我想到的是这样的:
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
这将断言方法 foobar()
被正确的线程调用...
SomeType foobar(...) {
assert(Thread.currentThread() == theCorrectThread);
...
}
...如果在第一个 foobar()
调用之前的代码中某处设置了
Thread theCorrectThread = new Thread(...);
but I would prefer something with static checking similar to @Nullable
我自己对注解知之甚少。我知道它们可用于将元信息附加到已编译的 类,并且我知道程序可以通过调用 Class
对象的方法在 运行 时获取该信息,但是如果注释可以通过任何方式定义 compile-time 行为,那超出了我的知识范围。
无论如何,这可能是一个有争议的问题。当编译器处理 .java 文件时,它无法判断哪个线程或哪些线程可能执行它包含的代码。
Checker Framework enables the creation of compile-time static checkers that verify program correctness. Its GUI Effect Checker is similar to what you want. Here is an abridged excerpt from its manual:
One of the most prevalent GUI-related bugs is invalid UI update or invalid thread access: accessing the UI directly from a background thread.
If a background thread accesses a UI element such as a JPanel (by calling a JPanel method or reading/writing a field of JPanel), the GUI framework raises an exception that terminates the program.
It is difficult for a programmer to remember which methods may be called on which thread(s). The GUI Effect Checker solves this problem. The programmer annotates each method to indicate whether:
- It accesses no UI elements (and may run on any thread).
- It may access UI elements (and must run on the UI thread).
The GUI Effect Checker statically enforces that UI methods are only called from the correct thread.
GUI 效果检查器经过调整以检测和防止 GUI 线程错误,而您担心的是客户端-服务器线程错误。但是,原则是相同的,您应该能够通过相对较少的更改使 GUI Effect Checker 适应您的需要。
有一个 paper 讨论了使用 GUI Effect Checker 的案例研究。
另一种方法是采用 bug finder 来查找多线程应用程序中的错误。与 GUI 效果检查器不同,它不提供 保证 没有线程错误。但是在实践中是有效的,而且不需要你在程序中写任何注解。
最后,Checker Framework 还包含一个确保正确同步的 Lock Checker。这有助于防止并发错误,尽管它与您对线程安全的主要关注正交。
我正在编写一个使用多线程的项目的一部分,我正在尝试寻找检测代码中线程错误的方法。 是否有一些现有的工具可以帮助我做到这一点?
例如- 断言我的方法正在被正确的线程调用 要么 某种带有注释的静态检查,类似于@Nullable 和@NotNull,以检测我的代码何时从错误的线程调用方法。
虽然项目是多线程的,但几乎不需要同步,因为不同的线程不会访问相同的对象,它们有自己的实例。 从广义上讲,一次有四个线程运行
- 服务器线程=维护游戏状态一个或多个 客户
- 客户端线程 = 处理用户输入,维护本地 copy/cache 用于渲染的服务器数据
- NetworkMessage 线程 = 处理 incoming/outgoing 条消息 服务器和客户端之间
- 渲染线程=将本地数据处理为渲染信息 显卡
类 有时仅用于一个线程(例如用户输入轮询仅客户端),有时它们用于多个线程(例如弹丸的计算运动使用相同的代码同时在客户端和服务器上以减少感知延迟)。有好几次我从错误的线程调用方法,导致微妙且不可重复的错误和非常严重的显示器屏幕损坏(来自我的拳头)
目前我想到的是这样的:
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
这将断言方法 foobar()
被正确的线程调用...
SomeType foobar(...) {
assert(Thread.currentThread() == theCorrectThread);
...
}
...如果在第一个 foobar()
调用之前的代码中某处设置了
Thread theCorrectThread = new Thread(...);
but I would prefer something with static checking similar to @Nullable
我自己对注解知之甚少。我知道它们可用于将元信息附加到已编译的 类,并且我知道程序可以通过调用 Class
对象的方法在 运行 时获取该信息,但是如果注释可以通过任何方式定义 compile-time 行为,那超出了我的知识范围。
无论如何,这可能是一个有争议的问题。当编译器处理 .java 文件时,它无法判断哪个线程或哪些线程可能执行它包含的代码。
Checker Framework enables the creation of compile-time static checkers that verify program correctness. Its GUI Effect Checker is similar to what you want. Here is an abridged excerpt from its manual:
One of the most prevalent GUI-related bugs is invalid UI update or invalid thread access: accessing the UI directly from a background thread.
If a background thread accesses a UI element such as a JPanel (by calling a JPanel method or reading/writing a field of JPanel), the GUI framework raises an exception that terminates the program.
It is difficult for a programmer to remember which methods may be called on which thread(s). The GUI Effect Checker solves this problem. The programmer annotates each method to indicate whether:
- It accesses no UI elements (and may run on any thread).
- It may access UI elements (and must run on the UI thread).
The GUI Effect Checker statically enforces that UI methods are only called from the correct thread.
GUI 效果检查器经过调整以检测和防止 GUI 线程错误,而您担心的是客户端-服务器线程错误。但是,原则是相同的,您应该能够通过相对较少的更改使 GUI Effect Checker 适应您的需要。
有一个 paper 讨论了使用 GUI Effect Checker 的案例研究。
另一种方法是采用 bug finder 来查找多线程应用程序中的错误。与 GUI 效果检查器不同,它不提供 保证 没有线程错误。但是在实践中是有效的,而且不需要你在程序中写任何注解。
最后,Checker Framework 还包含一个确保正确同步的 Lock Checker。这有助于防止并发错误,尽管它与您对线程安全的主要关注正交。