java - 如何测试线程之间值的可见性

标签 java multithreading unit-testing testing concurrency

测试线程间值可见性的最佳方法是什么?

class X {
 private volatile Object ref;

 public Object getRef() {
  return ref;
 }

 public void setRef(Object newRef) {
  this.ref = newRef;
 }
}

类 X 公开了对 ref 对象的引用。如果并发线程读取和写入对象引用,则每个线程都必须查看已设置的最新对象。 volatile 修饰符应该做到这一点。这里的实现是一个示例,它也可以是同步的或基于锁的实现。

现在我正在寻找一种方法来编写一个测试,当值可见性不符合规定(读取旧值)时通知我。

如果测试确实消耗了一些 CPU 周期也没关系。

最佳答案

JLS 说明您应该做什么,以便在涉及“线程间操作”的应用程序中获得有保证的一致执行。如果您不做这些事情,执行可能会不一致。但它是否真的会不一致取决于您使用的 JVM、您使用的硬件、应用程序、输入数据,以及……当您运行应用程序时机器上可能发生的任何其他事情。

我看不出你提议的测试能告诉你什么。如果测试显示不一致的执行,它将证实正确进行同步的智慧。但是,如果运行几次测试只显示(显然)一致的执行,这并不能告诉您执行总是一致的。


例子:

假设您在(比方说)JDK 1.4.2(修订版 12)/Linux/32 位上运行测试,并在单处理器机器上运行“客户端”JVM 和选项 x、y、z。在运行测试 1000 次之后,您会发现如果省略 volatile似乎没有任何区别。您在那种情况下实际学到了什么?

  • 您还没有了解到它真的没有什么区别?如果您将测试更改为使用更多线程等,您可能会得到不同的答案。如果您再运行几千、几百万或十亿次测试,您可能会得到不同的答案。
  • 您还没有了解其他平台上可能发生的事情;例如不同的 Java 版本、不同的硬件或不同的系统负载条件。
  • 您还没有了解到省略 volatile 关键字是否安全

只有在测试显示出差异时,您才能学到一些东西。你学到的唯一一件事就是同步很重要 ...这是所有教科书等一直告诉你的:-)


底线:这是最糟糕的黑盒测试。它无法让您真正了解盒子内部发生的事情。要获得这种洞察力,您需要 1) 了解内存模型和 2) 深入分析 JIT 编译器发出的 native 代码(在多个平台上......)

关于java - 如何测试线程之间值的可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1414428/

相关文章:

java - thymeleaf 获得前 3 个对象

java - 如何使用控制台启动器从命令行运行 JUnit5 测试?

c - 尝试使用 pthread 实现竞争条件

java - 有没有办法合法地转换 Mockito 模拟对象?

unit-testing - Angular 2 单元测试错误 : Cannot resolve all parameters for 'RequestOptions'

java - @Document 注释中的 MongoDB 和 SpEL 表达式

java - 无法启动设备中的 Activity

c++ - 为什么引休眠眠会导致生产者消费者等待?

ruby-on-rails - EC2 中的 Ruby 多线程导致奇怪的行为

unit-testing - Nancy.Testing 是否支持嵌套 Razor View ?