解决方案 »

  1.   

    不能。
    比如你判断了a!=null;正准备执行else的语句。很不巧另外一个线程对你的map进行的操作,导致你的a现在等于null
    ,之前的线程继续执行else语句,这个时候a=null就会抛出空指针异常。一般比较常用的方法是用synchronized关键字
      

  2.   

    这肯定不行了,虽然ConcurrentHashMap是线程安全的,但是像你这样写,就不是了,你应该用synchronized块,把那段判断语句包围起来!
      

  3.   

    没有对a==null的操作,只有map.remove(),remove之后对a操作不会空指针吧,
    但即使这样确实存在数据不一致的问题,
    A对象内部已经实现了线程安全,主要考虑map增删和业务强相关,要保持线程安全就要加全局锁,但是性能又成问题
    是不是要考虑数据不一致出现的概率和成本,和加全局锁的性能代价,两难的选择
    除了synchronized外,还有没有其他方法可以减小颗粒度?
      

  4.   

    private final static ConcurrentMap<String, Future<Object>> cached = new ConcurrentHashMap<String, Future<Object>>();

    public Object get(String key) {
    Future<Object> future = cached.get(key);
    if (future == null) {
    Future<Object> newFutrue = new FutureTask<Object>(
    new Callable<Object>() {
    @Override
    public Object call() throws Exception {
    Object object = null;
    //TODO  真正的获取value
    return object;
    }
    });
    // put if absent 防止缓存穿透。防止同一个Key,多个线程没命中的情况下,穿透至缓存。
    future = cached.putIfAbsent(key, newFutrue);
    if (future == null) {
    future = newFutrue;
    }
    ((FutureTask<Object>) future).run();
    } Object value = null;
    try {
    value = future.get(30, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (ExecutionException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (TimeoutException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    return value;
    }本地缓存,请用Future   解决两个问题,
    1   不用同步  2  解决缓存穿透,防止同一个KEY 没命中之后,同时访问后端。
      

  5.   

    正确的用法是:
    V v = map.get(k);
    if (v == null) {
      V _v = new V();
      v = map.putIfAbsent(k, _v);
      if (v == null) {v = _v;}
    }
    这段代码可以在线程中执行,得到正确的 v。