问答

请教一下关于 SynchronizedList以及ConcurrentHashMap锁的问题

作者:admin 2021-05-07 我要评论

想请教一下为什么 SynchronizedList 是读写均加锁,而 ConcurrentHashMap 只有写加了锁,读并没有加锁。 查询了相关资料,ConcurrentHashMap 读不加锁是因为 Nod...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

想请教一下为什么 SynchronizedList 是读写均加锁,而 ConcurrentHashMap 只有写加了锁,读并没有加锁。
查询了相关资料,ConcurrentHashMap 读不加锁是因为 Node<K,V> 的 val 是用 volatile 声明的,因此保证了他的可见性,这里的 val 是一个对象。
但是我发现 SynchronizedList 中 list 是用 final 声明的, 而没有使用 volatile。
而根据查询到的资料说 volatile 声明对象或者数组,只能让其引用可见,那么他的元素/属性是如何保证可见呢?
自己做了一些简单的测试, 发现 volatile 声明的对象或者数组,他们的属性或者元素都是可见的(也有说是JIT优化产生的结果)如果 volatile 可以实现读的安全的话,SynchronizedList 是否可以使用 volatile 声明 list 而不给读加锁?

public static void main(String[] args) {
    VolatileDemo volatileDemo = new VolatileDemo();
    new Thread(() -> {
      long start = System.currentTimeMillis();
      System.out.println(start);
      for (int i = 0; i < 1000; i++) {
        try {
          volatileDemo.put(i);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      System.out.println("end");
      System.out.println(System.currentTimeMillis() - start);
    }).start();
    
    new Thread(() -> {
      for (; ; ) {
        volatileDemo.printNew();
      }
    }).start();
  }
  
  static class FlagClass{
      boolean hasNew = false;
  }
###

ConcurrentHashMap 是采用非阻塞算法实现的,就算是在写的情况下,一般也不会加锁。使用cas速度很快,就是实现相当复杂。SynchronizedList 就可以看成是一个普通的list,给方法都加上了同一个锁来保证安全,这样实现效率非常低。至于volatile 只能保证可见性,不能保证线程安全。就像你说的,如果放在引用上,只能保证引用的可见性。

###

设计思路不一样,ConcurrentHashMap的读追求的是最终一致性,size()方法尤为明显。

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 请教一下关于 SynchronizedList以及Con

    请教一下关于 SynchronizedList以及Con

  • el-upload 上传以及读取问题

    el-upload 上传以及读取问题

  • 大佬们antd Tree switcherIcon 如何分

    大佬们antd Tree switcherIcon 如何分

  • 千万级模糊搜索解决方案

    千万级模糊搜索解决方案

腾讯云代理商
海外云服务器