由于我正在撰写专注于并发方面的分析器,我正在寻找一个在中使用同步机制的良好人工示例爪哇即可。我的探查器可以看到与线程相关的一些操作;例如:
所以我正在寻找的是一个似乎在乍一看中理解的Java程序,但在执行它时,你开始怀疑结果。我希望我的探查器可能能够检测到后台发生了什么。
为了澄清自己,我举一个例子,Brian Goetz撰写的Java Concurrency in Practice一书给出了“有毒”代码示例,这些代码用于学习原因。
@NotThreadSafe
public class ListHelper<E> {
public List<E> list =
Collections.synchronizedList(new ArrayList<E>());
...
public synchronized boolean putIfAbsent(E x) {
boolean absent = !list.contains(x);
if (absent)
list.add(x);
return absent;
}
}
这是通过方法putIfAbsent
的线程安全类的扩展。由于list
已同步,但putIfAbsent
使用另一个锁来保护状态,就像列表中定义的方法一样。
探查器可以显示使用过的监视器锁和用户的惊讶(或者不是......),用户会看到有两个可能的监视器锁,而不是一个。
我不太喜欢这个例子,但我不会问,如果我已经有很多好的例子。
我发现我的问题与此类似:What is the most frequent concurrency issue you've encountered in Java?和Java concurrency bug patterns。
但他们只提到破坏的并发程序。我也在寻找线程安全的实现,但仍然不明显它们是线程安全的。
答案 0 :(得分:11)
查看list of FindBugs bug descriptions,特别是属于多线程正确性类别的那些(右表列)。
这些错误中的每一个都包含有关特定习语为什么不好以及如何解决的参考。
答案 1 :(得分:3)
我会回到过去,比如大概七年或更长时间,并从java.util.concurrent之前的时代找到一些开源代码。几乎任何推动其自身并发的东西都会有一些微妙的错误,因为并发很难做到。
答案 2 :(得分:3)
这个怎么样?
class ObjectReference {
private volatile Object obj = null;
public void set(Object obj) {
if (obj == null) {
throw new IllegalArgumentException();
}
this.obj = obj;
synchronized (this) {
notifyAll();
}
}
/**
* This method never returns null
*/
public Object waitAndGet() {
if (obj != null) {
return obj;
}
synchronized (this) {
wait();
return obj;
}
}
}
您实际上可以从null
获得waitAndGet()
。见 - Do spurious wakeups actually happen?
答案 3 :(得分:2)
Dining philosophers problem是一个经典的并发示例。 This link有一种可能的解决方案,可以在网络上找到更多解决方案。
如第一个链接所述,此示例说明了许多常见的并发问题。请让您的探查器显示它可以跟踪的数量!
答案 4 :(得分:2)
请参阅The Java Specialists' Newsletter以获得一致的小型Java谜题流,其中许多都符合您的测试需求。
答案 5 :(得分:1)
我建议四处寻找(或询问作者) IBM ConTest基准测试套件,因为它包含许多Java并发错误(遗憾的是不是大型开源程序)。这个基准测试的好处是已经记录了错误(类型和位置)。
如果你想找到更多的程序,我建议你看一下软件测试/并发程序质量领域的一些研究论文。他们应该指出他们在研究中使用的样本程序。
如果所有其他方法都失败了,您可以尝试在GitHub(或类似服务)上搜索包含必要的并发机制(即同步)的存储库。您可能会发现大量的Java代码,唯一的问题是没有记录错误(除非您查找提交修复)。
我认为这三个建议将为您提供足够的程序来测试您的并发分析器。
答案 6 :(得分:0)