Maison  >  Article  >  Java  >  Explication détaillée de la façon dont Java utilise ConcurrentHashMap et les compteurs pour implémenter les verrous

Explication détaillée de la façon dont Java utilise ConcurrentHashMap et les compteurs pour implémenter les verrous

黄舟
黄舟original
2017-05-28 09:12:342432parcourir

Cet article présente principalement les informations pertinentes sur Java utilisant ConcurrentHashMap et counter pour implémenter des verrous. Les amis dans le besoin peuvent se référer à

java. Utilisez ConcurrentHashMap et les compteurs pour implémenter des verrous

Dans certains scénarios, nous souhaitons que les threads soient mis en file d'attente en fonction de certaines données commerciales. Le code simple est le suivant :

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

public class TestServiceImpl {
  private static ConcurrentHashMap<Long, LockObj> lockMap = new ConcurrentHashMap<Long, LockObj>(40);

  public void test(Long userId){
    LockObj lock = tryLock(userId);
    synchronized (lock) {
      try{
        //处理业务
      }
      finally{
        unLock(lock);
      }
    }
  }

  private LockObj tryLock(Long key) {
    LockObj curVal = new LockObj(key);
    LockObj preVal = lockMap.putIfAbsent(key, curVal);
    if (null == preVal) {
      curVal.inc();
      return curVal;
    }
    else{
      preVal.inc();
    }
    return preVal;
  }

  private void unLock(LockObj lock){
    if (lock.dec() <= 0){
      lockMap.remove(lock.getKey());
    }
  }

  public class LockObj {
    private long key = 0;
    private AtomicInteger count = new AtomicInteger(0);

    public LockObj(long key){
      this.key = key;
    }

    public int inc(){
      return count.incrementAndGet();
    }
    public int dec(){
      return count.decrementAndGet();
    }

    public long getKey(){
      return key;
    }

    @Override
    public String toString() {
      return "LockObj [key=" + key + ", count=" + count + "]";
    }
  }

}

File d'attente selon. à userId , Si chaque thread ne libère pas le verrou après le traitement des données, le compteur n'a pas besoin d'être utilisé. Mais si l'on ajoute l'opération de déverrouillage, il faut ajouter un calculateur. Parce qu'après que le thread a libéré le verrou, avant d'avoir le temps de sortir du bloc de code synchronisé, un autre thread appelle la méthode tryLock, puis le thread obtiendra le verrou d'un autre objet, comme par conséquent, la mise en file d'attente userId à l'aide du mot clé synchronisé échoue.

peut également être implémenté à l'aide de l'API de Guava.

import com.google.common.collect.Interner;
import com.google.common.collect.Interners;


public class TestServiceImpl {

  Interner<String> pool = Interners.newWeakInterner();

  public void test(Long userId) throws OspException {

    synchronized ( pool.intern(String.valueOf(userId))){
      //处理业务操作
    }
  }
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn