【问题标题】:Thread-safety unit testing线程安全单元测试
【发布时间】: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


【解决方案1】:

您可以尝试一些实用程序,例如 jcstress http://openjdk.java.net/projects/code-tools/jcstress/ 或 thread-weaver https://github.com/google/thread-weaver,它们将检测您的字节码并为您的实现生成压力测试。

【讨论】:

    【解决方案2】:

    您可以尝试通过在测试方法的线程中放置休眠来模拟竞争条件。但显然这不会是一个 100% 可靠的测试。我的建议是,只要您事先知道代码将被同时访问,您只需使代码线程安全。否则你会为我们心爱的同步错误打开空间......

    【讨论】:

      【解决方案3】:

      你在测试过程中遇到以下两个问题

      1. 根据所使用的硬件或 jvm,程序的行为可能会有所不同。
      2. 错误只发生在非常特定的线程和时序星座中。

      要解决第 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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-08
        • 2015-11-14
        • 2017-01-25
        • 2011-06-02
        • 1970-01-01
        • 1970-01-01
        • 2010-09-30
        相关资源
        最近更新 更多