ArrayList, Vector和CopyOnWriteArrayList对比学习
ArrayList线程不安全的例子
线程安全就是多线程访问时,采用加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据时脏数据。List接口下有两个实现,一个是ArrayList,另一个是Vector。从源码角度来看,因为Vector的方法前加了synchronized关键字,也就是同步。ArrayList是高效的,Vector则是线程安全的。
ArrayList不是线程安全的举个例子:一个ArrayList,在添加一个元素的时候,它有大体上有两步来完成:
- 在内部数组的size索引处存放此元素;
- 增大size的值
在单线程情况下,如果size是0,添加一个元素之后,此元素在位置0,而且size=1;
在多线程情况下,假设有两个线程,线程A现将元素放在0位置。但是此时CPU调度线程A暂停线程B得到运行机会,线程B也向ArrayList中添加元素,因为此时size仍然等于0(注意线程A只完成了添加的第一步,后面修该size的步骤还没做),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加size的值。对于这个ArrayList来说,元素实际上只有一个,存放在位置0,二size却等于2。
附:ArrayList的add方法:
public boolean add(E e) {
// Increments modCount!!
ensureCapacityInternal(size + 1);
// 现在size处放置元素, 然后在增加size
elementData[size++] = e;
return true;
}
测试ArrayList线程不安全的demo:
public class UnsafeArrayListDemo implements Runnable {
private List<Integer> list = new ArrayList<Integer>();
public void run() {
try {
Thread.sleep((int)Math.random());
} catch (Exception e) {
e.printStackTrace();
}
list.add(1);
}
public static void main(String[] args) throws Exception {
ThreadGroup group = new ThreadGroup("group");
UnsafeArrayListDemo unsafeArrayListDemo = new UnsafeArrayListDemo();
for(int i=0; i<10000; i++) {
Thread t = new Thread(group, unsafeArrayListDemo, String.valueOf(i));
t.start();
}
// 等待线程组执行完毕
while(group.activeCount() > 0) {
Thread.sleep(100);
}
System.out.println(unsafeArrayListDemo.list.size());
}
}
现在看下Vector中的add方法:
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
基本上和ArrayList一样,都是先添加,然后对size自增,唯一不同的是这个方法上加了关键字synchronized。可以在ArrayList的demo换成Vector来测试(本人已经测试过了,就不附代码了,直接替换ArrayList就好了)。Vector相对于ArrayList也会很暴力,为了线程安全就对方法加上了synchronized。
Vector的方法在单个进行调用的时候虽然是线程安全的,但是进行方法的复合操作的时候仍然是线程不安全的,还需要客户端来进行加锁。
Vector复合操作不安全的例子
public class VectorDemo {
// 获取最后一个元素
public static Object getLast(Vector list) {
int lastIndex = list.size() - 1;
return list.get(lastIndex);
}
// 删除最后一个元素
public static void deleteLast(Vector list) {
int lastIndex = list.size() - 1;
list.remove(lastIndex);
}
}
像这种先获取值,然后进行操作都是不安全的,简单的方法就是在方法内部进行加锁。问题来了,怎么加锁呢?
ArrayList, Vector和CopyOnWriteArrayList对比学习的更多相关文章
- ArrayList、LinkedList、Vector、CopyOnWriteArrayList的区别和源码分析
1. ArrayList ArrayList 是一个数组队列,相当于动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAccess, ...
- ArrayList & Vector的源码实现
#ArrayList & Vector #####前言: 本来按照计划,ArrayList和Vector是分开讲的,但是当我阅读了ArrayList和Vector的源码以后,我就改变了注意,把 ...
- Arraylist Vector Linkedlist区别和用法 (转)
ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素,但是插入数据要设计到数组元素移动等内存操作,所以索引数据快插入数据慢 ...
- java集合(ArrayList,Vector,LinkedList,HashSet,TreeSet的功能详解)
说起集合,我们会潜意识里想到另外一个与之相近的名词——数组,OK!两者确实有相似之处,但也正是这点才是我们应该注意的地方,下面简单列出了两者的区别(具体功能的不同学习这篇文章后就会明白了): 数组 长 ...
- Java集合详解1:一文读懂ArrayList,Vector与Stack使用方法和实现原理
本文非常详尽地介绍了Java中的三个集合类 ArrayList,Vector与Stack <Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整 ...
- 对比学习 ——simsiam 代码解析。
目录 1 : 事先准备 . 2 : 代码阅读. 2.1: 数据读取 2.2: 模型载入 3 训练过程: 4 测试过程: 5 :线性验证 6 : 用自己数据集进行对比学习. 第一: 改数据集 : ...
- [数据结构1.2-线性表] 动态数组ArrayList(.NET源码学习)
[数据结构1.2-线性表] 动态数组ArrayList(.NET源码学习) 在C#中,存在常见的九种集合类型:动态数组ArrayList.列表List.排序列表SortedList.哈希表HashTa ...
- 突破瓶颈,对比学习:Eclipse开发环境与VS开发环境的调试对比
曾经看了不少Java和Android的相关知识,不过光看不练易失忆,所以,还是写点文字,除了加强下记忆,也证明我曾经学过~~~ 突破瓶颈,对比学习: 学习一门语言,开发环境很重,对于VS的方形线条开发 ...
- MongoDB(五)mongo语法和mysql语法对比学习
我们总是在对比中看到自己的优点和缺点,对于mongodb来说也是一样,对比学习让我们尽快的掌握关于mongodb的基础知识. mongodb与MySQL命令对比 关系型数据库一般是由数据库(datab ...
随机推荐
- Mysql按数字大小排序String字段
问题是这样的,当我们按由大到小的顺序排序一组数字的时候,它应该如此: 9800 8000 900 但如果是这些数字是以String类型存储的话,直接排序的结果会是这样: 9800 900 8000 当 ...
- OpenGL tutorial资源在mac yosemite下的cmake生成工程问题
如果你在使用cmake -G Xcode -Wno-dev OpenGL_Tutorial 时,出现了pThread.h not found的错误, 碰巧你和我一样使用的还是 2.8 版本的cmake ...
- 使用inno setup 制作安装文件-demo1
; 脚本由 Inno Setup 脚本向导 生成! ; 有关创建 Inno Setup 脚本文件的详细资料请查阅帮助文档! #define MyAppName "查体管理系统" # ...
- django url 中的namespace详解
[引子] django是一个比较全能的web框架,比如它实现了自己的orm模型来对接不同的数据库.并提供了方便的数据接口:django牛逼的地方 还有许多,如他实现了自己的模板语言,这样我们就能方便的 ...
- 交叉验证(CrossValidation)方法思想简介[zz]
以下简称交叉验证(Cross Validation)为CV.CV是用来验证分类器的性能一种统计分析方法,基本思想是把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(train se ...
- SpringMVC 封装返回结果对象
/*** *请求返回的最外层对象 **/ public class Result<T>{ /*错误码*/ private Integer code; /*提示信息*/ private St ...
- Android API 指南
原文链接:http://android.eoe.cn/topic/android_sdk Android API 指南 - Android API Guides 应用的组成部分 - Applicati ...
- andorid 直接解压后的xml的解密
1.首先可以去看看这个gitHub: https://github.com/tracer0tong/axmlprinter 2.把apk.py 和 axmlprinter.py下载下来. 2.1(如果 ...
- Atitit 图像处理 halcon类库的使用 范例边缘检测 attilax总结
Atitit 图像处理 halcon类库的使用 范例边缘检测 attilax总结 1.1. 安装halcon11 ..体积大概1g压缩模式1 1.2. Halcon的科技树1 1.3. 启动 &qu ...
- [svc]centos7的服务治理-systemd
经常用到的高频命令小结 - 所有服务unit放在这里 ll /usr/lib/systemd/system - 默认启动级别 [root@n1 ~]# ll /etc/systemd/system/d ...