java 集合读写同步_JAVA多线程学习十六 - 同步集合类的应用

1.引言

在多线程的环境中,如果想要使用容器类,就需要注意所使用的容器类是否是线程安全的。在最早开始,人们一般都在使用同步容器(Vector,HashTable),其基本的原理,就是针对容器的每一个操作,都添加synchronized来进行同步,此种方式尽管简单,但是其性能是非常地下的,所以现在已经不怎么使用了。人们普遍会使用并发的容器,在JDK1.5之后,针对基于散列的Map,提供了新的ConcurrentHashMap,针对迭代需求的list,提供了CopyOnWriteList.

2.ConcurrentHashMap

ConcurrentHashMap使用了一种分段锁的策略,使得map可以被多个读写线程并行的访问。基本可以认为是将map的key值范围分为多个段,这样多个线程访问的时候,他们需要访问的key值在不同的段,所以可以互相不干扰,

使用不同的锁对象来进行并发操作。

ConcurrentHashMap在使用迭代器遍历的时候,不会报ConcurrentModificationException,提供“弱一致性”。在遍历迭代的时候,也会反应出在迭代器创建之后的数据修改。

应用场景

针对一般的有并发需求的map,都应该使用ConcurrentHashMap. 它的性能优于Hashtable和synchronizedMap。

缺点

不是强一致性

由于是采用的分段锁策略,所以一些数据不能保证强一致性。比如针对容器的size方法,由于线程A只是获得了自己的分段锁,它不能保证其他线程对容器的修改,所以此时线程A可能使用size,会得到不稳定数据。这种情况下,是对同步性能的一些折衷。如果业务需求必须满足强一致性,才会需要对整个Map进行锁操作。并发容器的弱一致性的概念背景,是在高并发情况下,容器的size和isEmpty之类的方法,用处不大,所以可以忍受数据不一致性。

3.CopyOnWrite容器

在JDK1.5之后,java.util.concurrent引入了两个CopyOnWrite容器,分别是CopyOnWriteArrayList, CopyOnWriteArraySet.

顾名思义,CopyOnWrite就是在write操作之前,对集合进行Copy,针对容器的任意改操作(add,set,remove之类),都是在容器的副本上进行的。并且在修改完之后,将原容器的引用指向修改后的副本。

如果线程A得到容器list1的iterator之后,线程B对容器list1加入了新的元素,由于线程A获得list1的iterator时候在线程B对list1进行修改前,所以线程A是看不到线程B对list1进行的任何修改。

具体到源码,看一下add操作

48304ba5e6f9fe08f3fa1abda7d326ab.png

/**

* Appends the specified element to the end of this list.

*

* @param e element to be appended to this list

* @return {@code true} (as specified by {@link Collection#add})

*/

public boolean add(E e) {

final ReentrantLock lock = this.lock;

lock.lock();

try {

Object[] elements = getArray();

int len = elements.length;

Object[] newElements = Arrays.copyOf(elements, len + 1);

newElements[len] = e;

setArray(newElements);

return true;

} finally {

lock.unlock();

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

可以发现,写操作是会有个锁lock.lock(),这保证了多线程写操作之间的同步。之后使用Arrays.copyOf来进行数组拷贝,在修改完成后,setArray(newElements)将原来的数组引用指向新的数组。

应用场景

经常用在读多写少的场景,比如EventListener的添加,网站的category列表等偶尔修改,但是需要大量读取的情景。

缺点

1.数据一致性的问题。

因为读操作没有用到并发控制,所以可能某个线程读到的数据不是实时数据。

2.内存占用问题。

因为写操作会进行数据拷贝,并且旧有的数据引用也可能被其他线程占有一段时间,这样针对数据比较大的情况,可能会占用相当大的内存。并且由于每次写操作都会占用额外的内存,最后进行的GC时间也可能相应的增加。

4.HashSet

HashSet内部是用的HashMap,只用了HashMap的key。

同步集合

传统集合类在并发访问时的问题说明:死锁死循环

传统方式下用Collections工具类提供的synchronizedCollection方法来获得同步集合,分析该方法的实现源码

Java5中提供了如下一些同步集合类:

通过看java.util.concurrent包下的介绍可以知道有哪些并发集合

ConcurrentHashMap

CopyOnWriteArrayList

CopyOnWriteArraySet

传统方式下的Conllection在迭代结合时,不允许对集合进行修改。

根据AbstractList的checkForComodification方法的源码,分析产生ConcurrentModificationException异常的原因。

48304ba5e6f9fe08f3fa1abda7d326ab.png

public class User implements Cloneable{

private String name;

private int age;

public User(String name, int age) {

this.name = name;

this.age = age;

}

public boolean equals(Object obj) {

if(this == obj) {

return true;

}

if(!(obj instanceof User)) {

return false;

}

User user = (User)obj;

//if(this.name==user.name && this.age==user.age)

if(this.name.equals(user.name)

&& this.age==user.age) {

return true;

}

else {

return false;

}

}

public int hashCode() {

return name.hashCode() + age;

}

public String toString() {

return "{name:'" + name + "',age:" + age + "}";

}

public Object clone() {

Object object = null;

try {

object = super.clone();

} catch (CloneNotSupportedException e) {}

return object;

}

public void setAge(int age) {

this.age = age;

}

public String getName() {

return name;

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/279119.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu自定义菜单_如何自定义Ubuntu的每日消息

ubuntu自定义菜单Ubuntu displays an informative message, known as the message of the day, when a user logs in at the terminal. The MOTD is fully customizable — you can add your own text and other dynamic data. 当用户在终端上登录时,Ubuntu将显示信…

火狐web开发清楚缓存_如何使用Firefox的Web开发工具

火狐web开发清楚缓存Firefox’s Web Developer menu contains tools for inspecting pages, executing arbitrary JavaScript code, and viewing HTTP requests and other messages. Firefox 10 added an all-new Inspector tool and updated Scratchpad. Firefox的Web Develop…

Java基类共同属性设置_多选择基类的访问属性-Java初学笔记

多选择基类的访问属性你现在知道在定义类的访间属性时可用的选择项,你希望使用这些类定义子类。你知道在类继承上这些属性所具有的效果,但是你如何决定到底应该使用哪一个呢?这里没有死板和现成的规则,你选择的访问属性取决于在将来你想用类…

IT:如何在Windows Server 2008 R2上安装Hyper-V虚拟化

Windows Server 2008 R2 and later releases of the product ship with a virtualization platform called Hyper-V, which works quite well since it’s built into Windows. Today we’re going to show you how to install it. Windows Server 2008 R2和更高版本的产品附带…

FineReport单行与数据库交互的方法

1. 问题描述 我们在做一张报表填报的时候经常会遇到需要在一行进行添加动作,将该行数据直接与数据库交互,执行存储过程过程。我们可以通过每一行增加帆软“插入”按钮实现插入动作,并且在控件事件中增加和数据库的交互,但当事件…

java cas volatile_每日一个知识点:Volatile 和 CAS 的弊端之总线风暴

每日一个知识点系列的目的是针对某一个知识点进行概括性总结,可在一分钟内完成知识点的阅读理解,此处不涉及详细的原理性解读。一、什么是总线风暴总线风暴,听着真是一个帅气的词语,但如果发生在你的系统上那就不是很美丽了&#…

SqlServer之代码块相关

转载必需注明出处:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/sqlserver-codeblock/ 一、go语句 Go语句是SqlServer中用来表示当前代码块结束提交并确认结果的语句。 Go语句不能和其他Sql命令卸载同一行上! 定义的局部变量作用域局限在定义它的代码…

010 使用list和tuple

list Python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素。 比如,列出班里所有同学的名字,就可以用一个list表示: >>> classmates [Michael, Bob, Tracy] >>&g…

IT:如何使用Server 2008 R2上的远程桌面服务设置自己的终端服务器

In today’s IT learning article, we are going to take a look at installing Terminal Services, otherwise known as Remote Desktop Services, on a Server 2008 R2 machine. 在今天的IT学习文章中,我们将介绍在Server 2008 R2计算机上安装终端服务(也称为远程…

Win10 jdk的安装以及环境变量的配置,及需要注意的坑

此篇文章献给自己,希望下次长点记性 最近本人终于有时间开始学习appium,并且开始在电脑上配置环境,第一步就是在我那刚装的Win10 系统上安装jdk,过程并不顺利,由于之前都是用的win7,几乎都是一路的下一步&a…

Jenkins配置Findbugs做源代码安全扫描

2019独角兽企业重金招聘Python工程师标准>>> 此内容目标阅读用户:运维人员 配置步骤如下: Jenkins安装Findbugs插件 Jenkins系统管理 → 管理插件 → (可选插件)找到Findbugs及其依赖插件全部安装成功,Jenkins重启,即可…

如何从USB运行Windows 8 Developer Preview

Running Windows 8 from a USB should not be confused with installing Windows on a USB drive–in this case, instead of installing it on the drive, we’re just running it straight from the portable drive. Here’s how to do it. 从USB运行Windows 8不应与在USB驱动…

火狐查cookie_Firefox 65默认会阻止跟踪Cookie

火狐查cookieMozilla today released Firefox 63, which includes an experimental option to block third-party tracking cookies, protecting against cross-site tracking. You can test this out today, but Mozilla wants to enable it for everyone by default in Firef…

chromebook刷机_如何将iTunes音乐移至Chromebook

chromebook刷机If you switch between platforms a lot, you know it’s a hassle to move your stuff around. Fortunately, music files don’t have any sort of DRM tying them to a specific platform the way that movies do, so you can copy and paste your library ar…

阿里巴巴Java开发手册终极版

2019独角兽企业重金招聘Python工程师标准>>> 一、编程规约: (一)命名风格 1. 【强制】 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。 反例: _name / __name / $Object / name_ / name$ / Object$ 2.…

ios6.1.6可用微信_这是iOS 12.1的新增功能,今天可用

ios6.1.6可用微信While iOS 12 is still fairly fresh, the first point release will be rolling out starting today. This brings a handful of new features, like Group Facetime, dual SIM support, camera improvements, new emoji, and more. 尽管iOS 12仍然相当新鲜&a…

esp32 cam工作电流_我如何在家工作:Cam的生产力之痛

esp32 cam工作电流Telecommuting is becoming more and more common these days, with many tech writers (myself included) working from home on a full-time basis. I get asked about how I work fairly often, so here’s the skinny. 如今,远程办公变得越来越…

NUMPY数据集练习 ----------SKLEARN类

123456<br><br># 1. 安装scipy&#xff0c;numpy&#xff0c;sklearn包import numpyfrom sklearn.datasets import load_iris# 2. 从sklearn包自带的数据集中读出鸢尾花数据集dataprint(data.data)123# 3.查看data类型&#xff0c;包含哪些数据data load_iris()pr…

java 伪异步 netty,大话netty系列之--伪异步BIO

生意规模扩大话说&#xff0c;老王和大明的生意越来越好&#xff0c;这就需要两个人增强业务往来&#xff0c;由于天南地北&#xff0c;两个人只能每次运输都需要雇一个人去运货(new 一个线程)&#xff0c;一个月下来&#xff0c;两人一算&#xff0c;人力成本太大了&#xff0…

如何使用Windows搜索在任何文件中搜索文本

Many of us rely on Windows Search to find files and launch programs, but searching for text within files is limited to specific file types by default. Here’s how you can expand your search to include other text-based files. 我们中的许多人都依赖Windows搜索…