2

スレッドセーフな方法で、次のデータ構造の変更 (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 のデュオに置き換えると、競合状態が発生します。

ここで(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()、この場合、毎回渡すために空のセットを作成する必要があるという追加のオーバーヘッドがあります。

于 2013-02-08T00:00:09.533 に答える