gpt4 book ai didi

java - 同步集合/列表的映射

转载 作者:行者123 更新时间:2023-11-29 10:05:26 25 4
gpt4 key购买 nike

我想在“Map of Sets”集合上实现一个变体,它将被多个线程不断访问。我想知道我正在进行的同步是否足以保证不会出现任何问题。

所以给出如下代码,其中Map、HashMap和Set是Java实现,Key和Value是一些任意对象:

public class MapOfSets {
private Map<Key, Set<Value>> map;

public MapOfLists() {
map = Collections.synchronizedMap(new HashMap<Key, Set<Value>());
}

//adds value to the set mapped to key
public void add(Key key, Value value) {
Set<Value> old = map.get(key);

//if no previous set exists on this key, create it and add value to it
if(old == null) {
old = new Set<Value>();
old.add(value);
map.put(old);
}
//otherwise simply insert the value to the existing set
else {
old.add(value);
}
}

//similar to add
public void remove(Key key, Value value) {...}

//perform some operation on all elements in the set mapped to key
public void foo(Key key) {
Set<Value> set = map.get(key);

for(Value v : set)
v.bar();
}
}

这里的想法是,因为我已经同步了 Map 本身,所以 get() 和 put() 方法应该是原子的,对吧?因此应该不需要对 Map 或其中包含的 Sets 进行额外的同步。那么这行得通吗?

或者,上述代码是否优于另一种可能的同步解决方案:

public class MapOfSets {
private Map<Key, Set<Value>> map;

public MapOfLists() {
map = new HashMap<Key, Set<Value>();
}

public synchronized void add(Key key, Value value) {
Set<Value> old = map.get(key);

//if no previous set exists on this key, create it and add value to it
if(old == null) {
old = new Set<Value>();
old.add(value);
map.put(old);
}
//otherwise simply insert the value to the existing set
else {
old.add(value);
}
}

//similar to add
public synchronized void remove(Key key, Value value) {...}

//perform some operation on all elements in the set mapped to key
public synchronized void foo(Key key) {
Set<Value> set = map.get(key);

for(Value v : set)
v.bar();
}
}

我让数据结构不同步,而是同步所有可能的公共(public)方法。那么哪些可行,哪些更好?

最佳答案

您发布的第一个实现不是线程安全的。考虑一下当两个具有相同 key 的并发线程访问 add 方法时会发生什么:

  1. 线程 A 执行该方法的第 1 行,并获得一个 null 引用,因为不存在具有给定键的项目
  2. thread B 执行该方法的第 1 行,并获得一个 null 引用,因为不存在具有给定键的项目 — 这将在 A< 之后发生/strong> 从第一次调用返回,因为 map 是同步的
  3. 线程 A 评估 if 条件为 false
  4. 线程 B 评估 if 条件为 false

从那时起,两个线程将继续执行 if 语句的 true 分支,您将丢失两个 value 对象之一。

您发布的方法的第二种变体看起来更安全。


但是,如果你可以使用第三方库,我建议你查看Google Guava ,因为它们提供并发多图 ( docs )。

关于java - 同步集合/列表的映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9553888/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com