证明以下代码不是线程安全的

2022-09-05 00:32:02

如何通过编写一些代码快速证明以下类不是线程安全的(因为它使用惰性初始化而不是使用同步)?换句话说,如果我正在测试以下类的线程安全性,我怎么能失败呢?

public class LazyInitRace {
  private ExpensiveObject instance = null;

  public ExpensiveObject getInstance() {
     if (instance == null)
        instance = new ExpensiveObject();
    return instance;
  }
}

答案 1

根据定义,竞态条件不能以确定性方式进行测试,除非您控制线程调度程序(您没有控制线程调度程序)。您可以做的最接近的事情是在方法中添加可配置的延迟,或者在问题可能显现的地方编写代码,并在循环中运行数千次。getInstance()

顺便说一句,这些都不能真正构成“证据”。形式验证会,但非常非常困难,即使对于相对少量的代码也是如此。


答案 2

你能强迫在测试中花很长时间来构建吗?如果是这样,只需从两个不同的线程调用两次,在足够短的时间内,第一个构造函数在进行第二个调用之前不会完成。您最终将构造两个不同的实例,这是您应该失败的地方。ExpensiveObjectgetInstance()

让天真的双重检查锁定失败将更难,请注意...(即使如果不指定变量,它也是不安全的)。volatile