如何Junit测试两个线程不同时访问的同步对象?

时间:2016-06-05 04:53:10

标签: java multithreading junit hashmap synchronized

有什么方法可以进行Junit测试以确保两个线程不同时访问同步对象(在我的情况下是同步块中的HashMap)?例如强制两个线程尝试访问并抛出异常。 谢谢你的帮助!

4 个答案:

答案 0 :(得分:1)

我对线程测试有帮助的最佳框架是Thread Weaver。至少它提供了一些确定性的线程调度方式,以及尝试查找竞争条件的有限(但有用)方法。

您甚至可以编写更复杂的线程调度方案,但这些测试将不可避免地是白盒测试。不过,这些也可以使用它们。

答案 1 :(得分:1)

  

有什么方法可以进行Junit测试以确保两个线程不能同时访问同步对象(在我的情况下是同步块中的HashMap)?

我不确定是否有一个测试框架来测试这个,但你肯定可以编写一些代码,试图通过多个线程反复访问受保护的HashMap。不幸的是,这很难可靠,因为正如@Bohemian所提到的,没有办法确定线程如何运行和访问地图,尤其是在音乐会中。

  

e.g。强制两个线程尝试访问并抛出异常。谢谢你的帮助!

是的,这不会因为两个原因而发生。如前所述,线程没有“强迫”。你只是没有那种控制水平。此外,由于同步问题,线程不会抛出异常,除非您执行synchronized(hashMap) { ... }以外的操作。当一个线程在地图上持有锁时,其他线程将阻塞,直到它释放锁。这很难检测和控制。如果您添加代码来执行检测和线程控制,那么您将进入Heisenberg情况,由于您的监视代码,您将影响线程行为。

测试正确的同步非常困难,通常无法做到。与其他开发人员一起检查代码,以确保HashMap在每次使用时完全同步,可能会提高效率。

最后,如果您担心HashMap,那么您可以考虑转移到ConcurrentHashMapCollections.synchronizedMap(new HashMap)。如果您使用一个操作进行多个地图调用,它们会处理竞争条件,它们会为您处理同步和保护实际地图。顺便说一句,HashTable被认为是旧班,不应该使用。

希望这有帮助。

答案 2 :(得分:0)

据我了解,你有一个与此类似的代码

synchronized(myHashMap) {
    ...
}

...这意味着线程在进入同步块时获取myHashMap提供的锁,并且所有其他尝试进入同一块的线程都必须等待,即no other thread can acquire the same lock

  

有什么方法可以进行Junit测试以确保两个线程不能同时访问同步对象(在我的情况下是同步块中的HashMap)?

知道了上述内容,你为什么要这样做?如果您仍想尝试,那么您可能需要查看此answer

最后,但并非最不重要。我建议您使用Hashtable,因为它是synchronized 。使用ConcurrentHashMap

答案 3 :(得分:0)

基本上,你不能,因为你无法控制线程的安排,更不用说协调它们来测试特定的行为。

其次,并非所有的构建服务器都是多线程的(我几天前就被这个问题所困扰 - 廉价的AWS实例只有1个CPU),所以你不能依赖甚至不仅仅知道线程可用用。来测试。

尝试重构代码,以便将锁定部分与应用程序分开并单独测试该逻辑......如果可以的话。