2

I'm trying to support modification (deactivate() function call) of the following data structure in a thread safe manner -

 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);
    }
}

If I were to replace the synchronization with ConcurrentHashMap & ConcurrentSkipListSet duo, there would be some race condition.

I was wondering if there was a cleaner way of achieving synchronization here (using java.util.concurrent)

4

2 回答 2

0

应该是没有以下实现的竞争条件:

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-08T04:27:15.133 回答
-1

我个人看不到这种方法的问题:

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);
}

putIfAbsent()map 中还有一个方法可以在“原子”操作中对地图进行获取/放置,但是在这种情况下它有额外的开销,你必须每次都构造一个空集才能传入。

于 2013-02-08T00:00:09.533 回答