从我读到的,单元测试线程安全没有“好的”通用解决方案。但我想为特定的问题提供一个很好的解决方案。
让我们考虑这个(虚拟)动态列表实现。 add
方法显然不是线程安全的。因为使它成为线程安全非常明显(让我们考虑一下我们不会实现任何remove
方法并保持虚拟),如何对代码进行单元测试以显示它实际上是 不是线程安全的,并且表明线程安全修复实际上有效(或似乎有效)?
public class ArrayList {
private int capacity = 2;
private Object[] content = new Object[capacity];
private int size;
public void add(Object object) {
if (size == capacity) {
ensureCapacity();
}
content[size++] = object;
}
public Object get(int index) {
if (index >= size) {
throw new IndexOutOfBoundsException();
}
return content[index];
}
private void ensureCapacity() {
int extendedCapacity = capacity * 2;
Object[] extended = new Object[extendedCapacity];
System.arraycopy(content, 0, extended, 0, size);
this.capacity = extendedCapacity;
this.content = extended;
}
}
答案 0 :(得分:2)
你可以尝试一些实用程序,比如jcstress http://openjdk.java.net/projects/code-tools/jcstress/或thread-weaver https://github.com/google/thread-weaver,他们会检测你的字节代码并为你的实现生成压力测试。
答案 1 :(得分:0)
您可以尝试通过将sleep放入测试方法的线程来模拟竞争条件。但显然它不是100%可靠的测试。我的建议是,只要事先知道它将被同时访问,您就可以使代码保持线程安全。否则你会为我们心爱的同步错误开辟空间......
答案 2 :(得分:0)
在测试期间,您面临以下两个问题
要解决第2点,您可以使用http://openjdk.java.net/projects/code-tools/jcstress/。它基本上测试了一个断言列表 负载不足。我认为这可能是您的用例的正确解决方案, 开发一个新的并发集合。
要解决第1点,您可以使用http://vmlens.com。它是一个检查程序中所有访问的字段是否运行的工具 可以根据java内存模型进行排序。 这样可以确保程序的顺序不依赖于硬件或jvm。
因此,如果您的用例是开发新的并发集合,我会使用http://vmlens.com进行检查 然后在具有多个内核的计算机上使用http://openjdk.java.net/projects/code-tools/jcstress/对其进行测试。
(我有偏见,我开发http://vmlens.com)