我必须编写一个引发竞争条件的单元测试,以便我可以测试稍后是否可以解决问题。
问题是竞争条件很少发生,可能是因为我的计算机只有两个核心。
代码如下:
class MyDateTime {
String getColonTime() {
// datetime is some kind of lazy caching variable declared somewhere(does not matter)
if (datetime == null) {
initDateTime(); //Uses lazy to initlialize variable, takes some time
}
// Colon time stores hh:mm as string
if (datetime.colonTime == null) {
StringBuilder sb = new StringBuilder();
//Now do some steps to build the hh:mm string
//...
//set colon time
datetime.colonTime = sb.toString();
}
return datetime.colonTime;
}
}
解释:
initDateTime 为 dateTime 分配一个新实例,因此,datetime.colonTime 之后为 null(因为我们想要延迟初始化它,如我之前所述)。
现在,如果线程 A 进入该方法,然后调度程序在它可以运行 initDateTime() 之前停止它。线程 B 现在运行 getColonTime(),发现日期时间仍然为 null 并对其进行初始化。 datetime.colonTime 为 null,因此执行第二个 if 块,并且 datetime.colonTime 获取 StringBuilder 的值。
如果调度程序停止该行和 return 语句之间的线程并恢复线程 A,则会发生以下情况:
由于 A 在调用 initDateTime 之前停止,A 现在调用 initDateTime(),这将有点resetdatetime 对象,再次将 datetime.colonTime 设置为 null。然后线程 A 将进入第二个 if 块,但调度程序会在 datetime.colonTime = sb.toString(); 之前中断 A。叫做。结论是,dateTime.colonTime 仍然为 null。
现在调度程序恢复 B 并且该方法返回 null。
我尝试通过让多个线程对 MyDateTime 的单个(最终)实例调用 getColonTime() 来引发竞争条件,但它仅在某些极其罕见的情况下失败:(
关于如何编写 JUnit“测试”有任何提示吗?
正如您所提到的,竞争条件很难一致地重现。然而,平均法则站在你这边。如果您创建一个预计会失败一百次之一的测试,然后让它发生一千次,您可能会在旧代码中相当一致地捕获错误。因此,为了符合 TDD 原则,您应该按照以前的方式开始编写代码,提出一个迭代足够多次的测试,以确保旧代码始终失败,然后更改为新代码并确保它不会失败。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)