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。 下面说一下这两个容器的缺点:
这两种模式只是提高了高并发中的性能,并不是说高并发项目中,用了这个容器就解决问题了,具体还是要看具体项目的场景及项目的代码设计。
ConcurrentMap与CopyOnWrite容器的更多相关文章
- 同步类容器和并发类容器——ConcurrentMap、CopyOnWrite、Queue
一 同步类容器同步类容器都是线程安全的,但在某些场景中可能需要加锁来保证复合操作. 符合操作如:迭代(反复访问元素,遍历完容器中所有元素).跳转(根据指定的顺序找到当前元素的下一个元素).条件运算. ...
- Copy-On-Write容器
Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改, ...
- java多线程-Java中的Copy-On-Write容器
Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改, ...
- Java再学习——CopyOnWrite容器
一,定义 CopyOnWrite容器即写时复制的容器.通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完 ...
- Java并发编程:CopyOnWrite容器的实现
Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...
- Java并发包中CopyOnWrite容器相关类简介
简介: 本文是主要介绍,并发容器CopyOnWriteArrayList和CopyOnWriteArraySet(不含重复元素的并发容器)的基本原理和使用示例. 欢迎探讨,如有错误敬请指正 如需转载, ...
- 聊聊并发-Java中的Copy-On-Write容器
详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp78 聊聊并发-Java中的Copy-On-Write容器 Cop ...
- Java多线程:CopyOnWrite容器
一.什么是CopyOnWrite容器 CopyOnWrite容器即写时复制的容器.通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然 ...
- Java并发中的CopyOnWrite容器
Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改, ...
随机推荐
- 选择、操作web元素-3
11月5日 Selenium 作业 3 登录 51job , http://www.51job.com 输入搜索关键词 "python", 地区选择 "杭州"( ...
- 前后台交互实现点击超链接通过指定的 url 去网络或者文件服务器下载文件
前台 VUE 界面: <el-table-column prop="attachment" align="center" label="附件详情 ...
- 配置maven访问nexus,配置项目pom.xml以发布maven项目到nexus中
maven访问nexus有三种配置方法,分别为: 项目pom.xml,优先级最高: user的settings.xml,优先级中,未在pom.xml中配置repository标签,则使用这个配置: m ...
- SQL 用到的操作符
1.LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式. SELECT column_name(s) FROM table_name WHERE column_name LIKE patte ...
- 大批量数据导出到Excel的实现
在平时的项目中,将数据导出到Excel的需求是很常见的,在此对一些常见的方法做以总结,并提供一种大数据量导出的实现. OLEDB 使用OLEDB可以很方便导出Excel,思路很简单,处理时将Exc ...
- 【373】LabelEncoder 相关
OneHotEncoder独热编码和 LabelEncoder标签编码 pandas.DataFrame.groupby
- C# 图像处理:获取鼠标位置信息(全局)
Point ms = Control.MousePosition; //获取鼠标位置 this.label2.Text = string.Format("{0}:{1}", ms. ...
- 学JS的心路历程 -非同步执行
JS是单线程的语言,也就是说同一时间只会执行一行程序,所以如果一段程序执行过久就会造成阻塞(blocking)的现象,必须等到它结束后才能执行下一段程序. 举个例子来说,如果我们今天要买便当,但是老板 ...
- 关于 uboot 的异常向量表
ldr r,address 表示将 address 地址中的内容存入 r0 中
- 安装 gradle
Gradle是一种现在很流程的构建工具,目前基本和Maven平分天下,而且大有取而代之的趋势.这篇教程教大家怎么在linux上安装Gradle. 一.获得一台linux服务器 要在linux下安装gi ...