从多个线程变换/读取HashMap,但一次只能一个线程

时间:2015-04-06 10:54:29

标签: java multithreading hashmap memory-barriers

我想在多线程环境中使用LinkedHashMap,其中多个线程可以访问hashmap(读/写),但是一次只有一个线程会这样做。因此不需要同步。但是,我需要确保一个线程所做的更改可以被以后访问它的任何其他线程读取。 例如:



    LinkedHashMap map = new LinkedHashMap();
    // Thread 1 
    map.put(key1, val1);

    // Thread 2. It starts after thread 1 has finished.
    Object val = map.get(key1);
    assert(val == val1);

..修改

有些人希望明确说明这个问题。所以这就是:

"我想确保对LinkedHashMap所做的更改对其他线程可见,即更改被写入主内存,而其他线程仅从主内存读取映射。没有地图的并发访问。"

3 个答案:

答案 0 :(得分:2)

答案取决于您执行的具体情况“一次只能有一个线程访问地图”。 (对时间的天真理解在这里是不适用的。同步是赋予程序时间意义的原因)。如果你在其他任何地方捎带外部同步,那么它可能是有效的,尽管是以一种脆弱的方式。

  

“我想确保对LinkedHashMap所做的更改是可见的   到其他线程,即更改被写入主内存,和   其他线程只从主内存中读取地图。“

然后您拥有来使用同步。没有别的东西会让你得到你所要求的语义。在同一个对象上使用synchronized保护所有访问是一种常规方式,但这会对读取产生不利影响。使用LinkedHashMap保护ReadWriteLock访问可能更高效,如果读取的次数大大超过写入次数。

答案 1 :(得分:0)

尝试使用ConcurrentHashMap。它在尝试获取锁定时扫描包含给定键的节点,如果未找到则创建并返回一个锁定。返回时,保证锁定。

实施例

    ConcurrentMap<String, String> concurrentMap = new ConcurrentHashMap<String, String>();
    concurrentMap.put("key", "value");
    String value = concurrentMap.get("key");

答案 2 :(得分:0)

为了线程间可见性,您仍然需要使用一些工具来确保写入映射和后续从其他线程读取之间的happens-before关系(JLS7 Section 17.4.5)。最简单的方法是你的synchronized块:

final Object lock = new Object();
...
synchronized(lock) {
     // write to map
}
...
synchronized(lock) {
     // read from map
}

或者,或许,以下条件中至少有一项适用于您的代码,因此您不会需要synchronized

  • 在启动线程中的任何操作之前,对线程的start()调用发生。
  • 线程中的所有操作都发生在任何其他线程从该线程上的join()成功返回之前。

,例如,你的作家在写作后开始读者,或者读者在做“#{1}}之前打电话给writer.join()。读取。