zoukankan      html  css  js  c++  java
  • ConcurrentMap与CopyOnWrite容器

    ConcurrentMap接口下有两个重要的实现:

      ConcurrentHashMap

      ConcurrentSkipListMap(支持并发排序功能,弥补ConcurrentHashMap)

    ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的HashTable,它们有自己的锁。只要多个修改操作发生在不同的段上,他们就可以并发进行。把一个整体分成了16个小段(Segment)。也就是最高支持16个线程的并发修改操作。这也是在多线程场景时减小锁的粒度从而降低锁竞争的一种方案。并且代码中大多共享变量使用volatile关键字声明,目的是第一时间获取修改的内容,性能非常好。

    下面 通过图形来对比一下

    先说明一张原来的形式的图:

    在t1线程执行写操作的时候,加入花费1s时间,在这1s的时间内,t2线程也来修改hashtable里面的其他参数的时候,t2线程只能在外面等待t1线程执行结束后,才能继续自己的操作。

    再看一张ConcurrentMap执行此类情况的图形:

    在t1线程操作的时候,t2线程可以操作ConcurrentMap的没t1操作的段(Segment),ConcurrentMap最高支持16个段,如果两个线程都是操作一个段(Segment),那没办法,只能等待t1执行完后,t2才能去执行。

    Copy-On-Write

    Copy-On-Write简称COW,是一种用于程序设计中的优化策略。

    JDK里的COW容器有两种:CopyOnWriteArrayList和CopyOnWriteArraySet,COW容器非常有用,可以在非常多的并发场景中使用到。

    什么是CopyOnWrite容器?

    CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。

     

     这个容器在写入的时候,会copy一份,然后在新的里面进行修改,此时,如果有其他线程要去读取数据的时候,会去原来的里面去读取,在写线程写入完毕后,对应的指针会指向新的内存空间,这种方式适合读多写少的情况。

    在多个写的过程中,jdk的底层是有锁的,只有在一个线程结束后,才允许另外一个线程去操作数据,不会出现数据不一致的现象。

    下面看一个ConcurrentHashMap的里面一个比较有意思的方法,

    public class UseConcurrentMap {
    public static void main(String[] args) {
    ConcurrentHashMap<String, Object> chm = new ConcurrentHashMap<String, Object>();
    chm.put("k1", "v1");
    chm.put("k2", "v2");
    chm.put("k3", "v3");
    chm.putIfAbsent("k4", "vvvv");
    // for (Map.Entry<String, Object> me : chm.entrySet()) {
    // System.out.println("key:" + me.getKey() + ",value:" + me.getValue());
    // }
    Iterator iter = chm.entrySet().iterator();
    while (iter.hasNext()) {
    Map.Entry me = (Map.Entry) iter.next();
    System.out.println("key:" + me.getKey() + ",value:" + me.getValue());
    }
    }
    }


    设想一个,这段代码的打印结果是什么?

    putIfAbsent的用法是先判断ConcurrentHashMap里面是否存在这个key,如果不存在,就把key和对应的value放入ConcurrentHashMap中,如果存在,则不操作ConcurrentHashMap。

    下面说一下这两个容器的缺点:
    这两种模式只是提高了高并发中的性能,并不是说高并发项目中,用了这个容器就解决问题了,具体还是要看具体项目的场景及项目的代码设计。


  • 相关阅读:
    KVM---利用 libvirt+qemu-kvm 创建虚拟机
    docker---安装docker
    Ubuntu---VIM 常用命令
    Ubuntu--- 安装VMware 报错 Build enviroment error!
    Ubuntu---不能打开 exfat 文件系统格式的 U盘解决方法
    Ubuntu---gedit 打开windows 下 .txt 文件乱码的解决方法
    MCS-51单片机的串行口及串行通信技术
    MCS-51单片机的定时器/计数器
    MCS-51单片机的中断系统
    计算机网络——网络层
  • 原文地址:https://www.cnblogs.com/shmilyToHu/p/6404589.html
Copyright © 2011-2022 走看看