Mutating/Reading 来自多个线程但一次一个线程的 HashMap
Mutating/Reading a HashMap from multiple threads but one thread at a time
我想在多线程环境中使用 LinkedHashMap,其中多个线程可以访问 hashmap (read/write),但一次只有一个线程这样做。因此不需要同步。但是,我需要确保一个线程所做的更改可以被稍后访问它的任何其他线程读取。
例如:
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);
..编辑
有些人希望明确说明问题。所以这里是:
"I want to ensure that the changes done to a LinkedHashMap are visible to other threads i.e the changes are written to the main memory, and other threads read the map from main memory only. There is no concurrent access of the map."
尝试使用 ConcurrentHashMap。它在尝试获取锁时扫描包含给定密钥的节点,如果找不到,则创建并 returning 一个。在 return 后,保证持有锁。
示例:
ConcurrentMap<String, String> concurrentMap = new ConcurrentHashMap<String, String>();
concurrentMap.put("key", "value");
String value = concurrentMap.get("key");
为了线程间可见性,您仍然需要使用一些工具来确保写入映射和后续从其他线程读取之间的 happens-before
关系 (JLS7 Section 17.4.5)。最简单的方法是你的 olde synchronized
块:
final Object lock = new Object();
...
synchronized(lock) {
// write to map
}
...
synchronized(lock) {
// read from map
}
或者,也许至少以下条件之一适用于您的代码,因此您不需要 synchronized
:
- 线程上对 start() 的调用发生在已启动线程中的任何操作之前。
- 线程中的所有操作先于任何其他线程成功地从该线程上的 join() returns 发生。
例如,您的写入器在写入后 reader 开始,或者 reader 在读取之前调用 writer.join()
。
答案取决于您执行的具体程度 "only one thread will access the map at one time"。 (对时间的天真理解在这里不适用。同步是赋予程序中时间意义的东西)。如果您在其他任何地方搭载外部同步,那么它可能会起作用,尽管是以一种脆弱的方式。
"I want to ensure that the changes done to a LinkedHashMap are visible
to other threads i.e the changes are written to the main memory, and
other threads read the map from main memory only."
那么您必须使用同步。没有别的可以让你得到你所要求的语义。使用 synchronized
保护同一对象上的所有访问是一种常规方法,但这会惩罚读取。如果读取次数大大超过写入次数,则使用 ReadWriteLock
来保护 LinkedHashMap
访问的性能可能更高。
我想在多线程环境中使用 LinkedHashMap,其中多个线程可以访问 hashmap (read/write),但一次只有一个线程这样做。因此不需要同步。但是,我需要确保一个线程所做的更改可以被稍后访问它的任何其他线程读取。 例如:
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);
..编辑
有些人希望明确说明问题。所以这里是:
"I want to ensure that the changes done to a LinkedHashMap are visible to other threads i.e the changes are written to the main memory, and other threads read the map from main memory only. There is no concurrent access of the map."
尝试使用 ConcurrentHashMap。它在尝试获取锁时扫描包含给定密钥的节点,如果找不到,则创建并 returning 一个。在 return 后,保证持有锁。
示例:
ConcurrentMap<String, String> concurrentMap = new ConcurrentHashMap<String, String>();
concurrentMap.put("key", "value");
String value = concurrentMap.get("key");
为了线程间可见性,您仍然需要使用一些工具来确保写入映射和后续从其他线程读取之间的 happens-before
关系 (JLS7 Section 17.4.5)。最简单的方法是你的 olde synchronized
块:
final Object lock = new Object();
...
synchronized(lock) {
// write to map
}
...
synchronized(lock) {
// read from map
}
或者,也许至少以下条件之一适用于您的代码,因此您不需要 synchronized
:
- 线程上对 start() 的调用发生在已启动线程中的任何操作之前。
- 线程中的所有操作先于任何其他线程成功地从该线程上的 join() returns 发生。
例如,您的写入器在写入后 reader 开始,或者 reader 在读取之前调用 writer.join()
。
答案取决于您执行的具体程度 "only one thread will access the map at one time"。 (对时间的天真理解在这里不适用。同步是赋予程序中时间意义的东西)。如果您在其他任何地方搭载外部同步,那么它可能会起作用,尽管是以一种脆弱的方式。
"I want to ensure that the changes done to a LinkedHashMap are visible to other threads i.e the changes are written to the main memory, and other threads read the map from main memory only."
那么您必须使用同步。没有别的可以让你得到你所要求的语义。使用 synchronized
保护同一对象上的所有访问是一种常规方法,但这会惩罚读取。如果读取次数大大超过写入次数,则使用 ReadWriteLock
来保护 LinkedHashMap
访问的性能可能更高。