【发布时间】:2015-08-10 14:15:39
【问题描述】:
根据我的阅读,单元测试线程安全没有“好的”通用解决方案。但我想要一个特定问题的好解决方案。
让我们考虑这个(虚拟)动态列表实现。 add 方法显然不是线程安全的。既然让它成为线程安全的很明显(让我们考虑一下我们不会实现任何remove 方法并保持它是虚拟的),如何对这段代码进行单元测试以显示它实际上是 em> 不是线程安全的,并表明线程安全修复确实有效(或似乎有效)?
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;
}
}
【问题讨论】:
-
你不能保证两个线程会以什么顺序通过
add方法或者什么时候可能被抢占——因此你不能编写一致的测试 -
我不认为它是重复的,因为我试图通过一个例子得到答案。但实际上无论如何都没有办法正确地对线程安全进行单元测试......它实际上是重复的。
-
证明多线程代码按预期工作的唯一方法是测试所有可能的“操作”序列化(即共享内存读取和写入)由各个线程执行。这对于小型算法和少量线程可能是实用的,但据我所知,这仍然是一个研究课题:我还没有听说过任何有助于枚举或强制 Java 字节码的不同序列化的工具。跨度>
-
您可以使用像 Awaitility 这样的库来模拟特定的排序,然后让线程对其进行很好的衡量。
标签: java multithreading unit-testing thread-safety