我正在尝试以线程安全的方式支持以下数据结构的修改(deactivate()函数调用)-
private static Map<String, Set<Integer>> dbPartitionStatus = new HashMap<String, Set<DBPartitionId>>();
public void deactivate(DBPartitionId partition) throws Exception {
synchronized (dbPartitionStatus) {
Set<DBPartitionId> partitions = dbPartitionStatus.get(serviceName);
if (partitions == null) {
partitions = new HashSet<DBPartitionId>();
}
partitions.add(partition);
dbPartitionStatus.put(serviceName, partitions);
}
}如果我将同步替换为ConcurrentHashMap & ConcurrentSkipListSet duo,将会出现一些竞争情况。
我想知道这里是否有更干净的方法来实现同步(使用java.util.concurrent)。
发布于 2013-02-08 12:27:15
在以下实现中应为无争用条件:
private final static ConcurrentMap <String, Set <DBPartitionId>> dbPartitionStatus =
new ConcurrentHashMap <String, Set <DBPartitionId>> ();
public void deactivate (DBPartitionId partition) {
Set <DBPartitionId> partitions = dbPartitionStatus.get (serviceName);
if (partitions == null)
{
partitions = new ConcurrentSkipListSet <DBPartitionId> ();
Set <DBPartitionId> p =
dbPartitionStatus.putIfAbsent (serviceName, partitions);
if (p != null) partitions = p;
}
partitions.add (partition);
}发布于 2013-02-08 08:00:10
我个人看不出这种方法有什么问题:
private static ConcurrentHashMap<String, ConcurrentSkipListSet<DBPartitionId>> dbPartitionStatus = new ConcurrentHashMap<>();
public bool deactivate(DBPartitionId partition) throws Exception {
ConcurrentSkipListSet<DBPartitionId> partitions = dbPartitionStatus.get(serviceName);
if (partitions == null) {
// Create a new set
partitions = new ConcurrentSkipListSet<DBPartitionId>();
// Attempt to add, if we add, ev will be null.
ConcurrentSkipListSet<DBPartitionId> ev = dbPartitionStatus.put(serviceName, partitions);
// If non-null, someone else has added it, so now use it.
if (ev != null)
partitions = ev;
}
// will return true if added succesfully...
return partitions.add(partition);
}map中还有putIfAbsent()方法,它可以在“原子”操作中对map进行get/put操作,但是在这种情况下,它有额外的开销,每次都必须构造一个空集来传递。
https://stackoverflow.com/questions/14763229
复制相似问题