螺纹安全单元测试

时间:2015-08-10 14:15:40

标签: java multithreading unit-testing thread-safety

从我读到的,单元测试线程安全没有“好的”通用解决方案。但我想为特定的问题提供一个很好的解决方案。

让我们考虑这个(虚拟)动态列表实现。 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;
    }
}

3 个答案:

答案 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)

在测试期间,您面临以下两个问题

  1. 根据所使用的硬件或jvm,程序可能会有所不同。
  2. 只有在非常具体的线程和时序星座中才会发生错误。
  3. 要解决第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