【问题标题】:How to Junit test a synchronized object not accessed by two threads at same time?如何Junit测试两个线程同时访问的同步对象?
【发布时间】:2016-10-04 22:46:21
【问题描述】:

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

【问题讨论】:

  • 这不是像测试 JVM 功能一样吗?如果是这样,它已经很好地测试了.. 否则,您可以创建一个可运行很长时间的可运行文件,并尝试访问您尝试测试的方法。运行此线程的两个实例以查看是否有任何冲突。如果锁定对象相同,则不会在同步块内发生。所以我觉得它就像测试不需要的JVM。
  • 我被要求提供一个缓存的实现,它提供 - 缓存的单个实例、类型安全和线程安全以及对这些功能中的每一个进行测试。我正在使用哈希映射为单实例和泛型的缓存和单例设计模式建模以提供类型安全。在测试代​​码时,我无论如何都不需要测试线程安全功能并寻找一些方法来解决这个问题。谢谢!
  • 出于缓存目的,使用ConcurrentHashMap,如果允许的话..那么您不必担心线程安全。
  • 那么有没有办法为线程安全提供单元测试呢?我为缓存实现了 put 和 get 方法,并委托给相应的 map 方法。当另一个线程尝试访问缓存而另一个线程对它有锁时是否会抛出异常,我可以进行测试。
  • 线程安全内置于ConcurrentHashMap,这是类的保证。你没有理由怀疑这一点,除非你觉得类实现或 java 库中存在错误。同步块场景也是如此。

标签: java multithreading junit hashmap synchronized


【解决方案1】:

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

我不确定是否有一个测试框架可以对此进行测试,但您当然可以编写一些代码来尝试使用许多线程一遍又一遍地访问受保护的HashMap。不幸的是,这很难可靠地做到,因为正如@Bohemian 所提到的,没有办法确定线程是如何运行和访问地图的,尤其是在一致的情况下。

例如强制两个线程尝试访问并引发异常。感谢您的帮助!

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

测试正确的同步非常困难,而且通常是不可能的。与其他开发人员一起审查代码以确保您的 HashMap 在每次使用时都完全同步,这样可能会更有效率。

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

希望这会有所帮助。

【讨论】:

  • 感谢详细解释!我知道这很困难,这就是为什么我在这里问,以防有一种我不知道的方法。
【解决方案2】:

据我了解,您的代码与此类似

synchronized(myHashMap) {
    ...
}

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

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

了解以上内容,您为什么要这样做?如果您仍然想尝试,那么您可能想看看这个answer

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

【讨论】:

  • 我被要求提供一个缓存的实现,它提供 - 缓存的单个实例、类型安全和线程安全以及对这些功能中的每一个进行测试。我正在使用哈希映射为单实例和泛型的缓存和单例设计模式建模以提供类型安全。在测试代​​码时,我无论如何都不需要测试线程安全功能并寻找一些方法来解决这个问题。谢谢!
  • HashTable 被认为是死类,不应使用。 ConcurrentHashMap 是它的现代替代品。
【解决方案3】:

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

其次,并非所有构建服务器都是多线程的(我只是在几天前被这个问题困扰 - 廉价的 AWS 实例只有 1 个 CPU),因此您甚至不能依赖超过已知的线程来进行测试与。

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-20
      • 1970-01-01
      • 2011-02-12
      • 2011-03-26
      • 2023-03-14
      • 2018-06-01
      • 2014-03-06
      • 1970-01-01
      相关资源
      最近更新 更多