Domanda

Come si esegue un get sicuro, se presente operazione su un concorrente Hash Map? (Stessa cosa come putIfAbsent)

Bad esempio, non molto thread-safe (controllo poi agire situazione):

ConcurrentMap<String, SomeObject> concMap = new ...

//... many putIfAbsent and remove operations

public boolean setOption(String id, Object option){
   SomeObject obj = concMap.get(id);

   if (obj != null){
      //what if this key has been removed from the map?
      obj.setOption(option);
      return true;
   }

   // in the meantime a putIfAbsent may have been called on the map and then this
   //setOption call is no longer correct

   return false;
}

Un altro cattivo esempio potrebbe essere:

   public boolean setOption(String id, Object option){
       if (concMap.contains(id)){
           concMap.get(id).setOption(option);
           return true;
       }
       return false;
    }

La cosa desiderabile è quello di non collo di bottiglia l'aggiungere, rimuovere e ottenere le operazioni per la sincronizzazione.

Grazie

È stato utile?

Soluzione

Cosa in cui sembra essere cercando di fare è quello di bloccare una chiave su più operazioni. Solo ogni operazione è atomica. Questi è un modo semplice per bloccare una chiave, solo per bloccare la carta.

Tuttavia nella "cosa succede se elimino un tasto" caso, tutto quello che puoi fare è di ritardare l'operazione di eliminazione fino a dopo il setOption si chiama. Il risultato dovrebbe essere lo stesso.

È sembrano essere cercando di risolvere un problema che non può avere bisogno di essere risolti. Non hai spiegato perché chiamare setOption dopo che un tasto viene eliminato o mentre la chiave è in attesa di essere eliminato è male.

Altri suggerimenti

Il metodo get() su un ConcurrentHashMap è atomico. Dal momento che la mappa non consente valori nulli, attrezzi get() "get se presente":. Se il risultato è null, la chiave non era presente

Non utilizzare containsKey / get, basta chiamare get. Se tale metodo restituisce null quindi la chiave non era presente altrimenti la chiave era presente, e vi entrato in possesso del valore che è stato mappato al momento della get.

Dalla documentazione:

  

Restituisce il valore a cui è associata la chiave specificata, oppure null se questa mappa non contiene la mappatura per la chiave.

Questo è come il tuo secondo esempio dovrebbe essere:

public boolean setOption(String id, Object option) {

    SomeObject opt = concMap.get(id);
    if (opt == null)
        return false;

    opt.setOption(option);
    return true;
}

Se avete bisogno di fare più operazioni in una singola chiave nel ConcurrentMap, è possibile utilizzare Blocca striping tecnica per ridurre la contesa, ecco un esempio di quadro Guava:

   private Striped<Lock> lock;
    public boolean setOption(String id, Object option) {
      try {
        Lock lock = concMap.get(id);
        lock.lock();
          if (concMap.contains(id)){
          concMap.get(id).setOption(option);
       return true;
   }
   return false;
        } finally {
         lock.unlock();
        }
    }

In alternativa, dal momento che Java 8: ConcurrentMap.compute è un nuovo metodo atomica, vedere come è fatto su un tasto:

    concMap.compute(keyId, (key, value) -> {
    dosmth; ... return key;  });

P.S. Eventuali variazioni sono con ConcurrentMap.computeIfPresent (), ecc.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top