【问题标题】:ConcurrentHashMap Behavior and QuestionsConcurrentHashMap 行为和问题
【发布时间】:2018-12-24 14:09:33
【问题描述】:

我有 4 个线程 - 2 个线程确实更新,2 个线程确实在 concurrentHashMap 上读取。代码如下:

private static ConcurrentHashMap<String, String> myHashMap = new ConcurrentHashMap<>();
private static final Object lock = new Object();

线程1和线程2的run方法(key和value都是字符串)

synchronized (lock) {
    if (!myHashMap.containsKey(key)) {
        myHashMap.put(key, value);
    } else {
        String value = myHashMap.get(key)
        // do something with the value
        myHashMap.put(key, value);
    }
}

线程 3 和线程 4 的 run 方法进行打印

for (Entry<String, String> entry : myHashMap.entrySet()) {
    String key = entry.getKey();
    String value = entry.getValue();
    System.out.println("key, " + key + " value " + value);
}

上面使用 ConcurrenHashMap 代码有什么问题吗? 因为当我阅读 Javadoc 并搜索网络时,我发现了以下声明:

  1. 在依赖线程安全但不依赖同步细节的程序中,此类与 Hashtable 完全可互操作。(注意 - 我了解打印线程结果可能不是最新结果,但只要更新线程正确执行就可以了。)
  2. 网站上也有人声称,同一个迭代器不能用于 2 个或更多不同的线程。所以我想知道打印方法是否在上面的 2 个线程中使用相同的迭代器。为什么我们不能在 2 个不同的线程中使用同一个迭代器?

对于需求,我想要并发读取而不阻塞,这就是我选择 ConcurrentHashMap 的原因。

【问题讨论】:

  • "上面的代码有问题吗?"如果不确切知道您想做什么以及如何做,我认为我们无法回答这个问题。你的代码 sn-p 太模糊了。有关如何制作更好的代码示例的说明,请参阅 stackoverflow.com/help/mcve
  • 更新了代码。用价值做事就意味着计算价值。
  • @Nathan Hughes 好吧,我需要确保更新线程已锁定,因此只有 1 个线程可以进行更新,其他线程必须等待。
  • 你只需要假设更新线程只能原子运行里面的所有代码。
  • 您在外部锁定下使用 CHM 破坏了它的全部目的。请改用原子merge()

标签: java data-structures concurrenthashmap


【解决方案1】:

您可以使用并发 hashmap 中的 putIfAbsent 方法,而不是使用 if else 块,其次您不应该在并发 hashmap 中使用外部锁定。

【讨论】:

  • 问题是由于计算的复杂性,我不能使用内置的 putIfAbsent 方法。为什么我们不应该使用外部锁?使用外部锁时是否有任何意外行为?还是仅仅因为性能?我敢打赌,性能不会比使用即使在读取线程上也会阻塞的 Hashtable 更差。
猜你喜欢
  • 2014-01-10
  • 1970-01-01
  • 2020-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多