dsa*_*ish 8 java findbugs thread-safety
下面的bean不是线程安全的:方法addIfNotExist不同步,因此由于竞争条件,相同的术语可能会被添加两次.我使用JCIP注释@ThreadSafe注释该类,希望FindBugs发现该实现不是线程安全的,并将其标记为错误,但事实并非如此.是否有任何工具可以识别代码库中的这些类型的错误?
方法addIfNotExist和isExist应该同步,以使这个bean线程安全.isExist方法也应同步吗?
package com.test;
import java.util.ArrayList;
import java.util.Collection;
import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.ThreadSafe;
@ThreadSafe
public class Dictionary {
@GuardedBy("this")
public Collection<String> terms = new ArrayList<String>();
public void addIfNotExist(final String input) {
if (!this.terms.contains(input)) {
this.terms.add(input);
}
}
public boolean isExist(final String input){
return this.terms.contains(input);
}
public void remove(final String input){
this.terms.remove(input);
}
}
Run Code Online (Sandbox Code Playgroud)
编写具有任何复杂程度的安全多线程代码都非常困难:这种类型的锁定(使用监视器)充满了各种间歇性竞争条件、死锁和活锁问题,这些问题通常会在升级到生产环境时逃避检测系统;如果可以的话,请考虑使用消息传递、软件事务内存或持久数据结构。
FindBugs(或者实际上任何静态分析工具)在检测非线程安全代码方面只能走这么远:根据其定义,竞争条件是时间敏感的 - 它们需要多次执行才能显现,因此静态分析在这方面失败,因为他们不运行任何代码,只寻找常见的代码签名。恕我直言,检测问题的最好方法是:
第二双眼睛——与熟悉代码的同行一起进行严格的代码审查——有助于发现对原作者来说并不明显的错误。
持续集成和详尽的自动化测试,在各种硬件上执行多线程性,并无情地调查任何“间歇性”测试失败。
回答第二个问题,是的,所有引用的方法都terms应该受到同步监视器的保护,无论是写操作还是读操作;考虑一下如果在没有同步的情况下线程 A 调用remove("BOB")而线程 B 正在调用,会发生什么情况- 线程 A 将压缩数组列表,而线程 B 将尝试遍历它。isExists("BOB")
充其量,您将无法确定 的结果isExists("BOB"),但 B 完全有可能间歇性地抛出IndexOutOfBounds异常,因为数组的大小可能在遍历时发生变化(即缩小)。
同步,虽然您仍然无法确定调用的顺序(由于调度的不确定性),但至少您可以保证 on 的操作terms将是原子的 - 也就是说,它们当前线程运行时不会被其他事物更改。
| 归档时间: |
|
| 查看次数: |
5000 次 |
| 最近记录: |