今天在网上看到一个问题,问除了加锁之外,有没有其他方法来保证线程安全?

---- copyonwrite机制

一、copyonwrite机制

机制实现:写时复制, 在往集合中添加数据的时候,先拷贝存储的数组,然后添加元素到拷贝好的数组中,然后用现在的数组去替换成员变量的数组。

这个机制:读写锁是一样的,但是比读写锁有改进的地方,那就是 读取的时候可以写入的 ,这样省去了读写之间的竞争。(同时写入怎么解决?----还是通过加锁)。

二、java中的copyonwrite

java中提供了两个利用这个机制实现的线程安全集合:

1、copyonwritearraylist

2、copyonwritearrayset  (copyonwritearrayset的底层实现是copyonwritearraylist)

我们接下来看看java的实现。

    public E get(int index) {
return get(getArray(), index);
}
private transient volatile Object[] array;  //volatile声明的数组,保证了读取的那一刻是最新的数据

接下来重点就是add方法了。下面的代码可以明显看出是明显需要reentrantlock加锁的,

接下来就是复制数据和添加数据的过程,在setArray的过程中,把新的数组赋值给成员变量array(这里是引用的指向,java保证赋值的过程是一个原子操作)。

  public void add(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
if (index > len || index < 0)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+len);
Object[] newElements;
int numMoved = len - index;
if (numMoved == 0)
newElements = Arrays.copyOf(elements, len + 1);
else {
newElements = new Object[len + 1];
System.arraycopy(elements, 0, newElements, 0, index);
System.arraycopy(elements, index, newElements, index + 1,
numMoved);
}
newElements[index] = element;
setArray(newElements);
} finally {
lock.unlock();
}
}

关于迭代,他采取的是获取传递给迭代器的数组值进行迭代,中间就算加入新的值也迭代不到。在构造函数中就直接赋值给final的成员变量。

        private final Object[] snapshot;

        private COWIterator(Object[] elements, int initialCursor) {
cursor = initialCursor;
snapshot = elements;
}

适用场景

copyonwrite的机制虽然是线程安全的,但是在add操作的时候不停的拷贝是一件很费时的操作。

所以使用到这个集合的时候尽量不要出现频繁的添加操作,而且在迭代的时候,数据也是不及时的,数据量少还好说,数据太多的时候,实时性可能就差距很大了。

适合:在多读取,少添加的时候,他的效果还是不错的(数据量大无所谓,只要你不添加,他都是好用的)。

java并发——copyonwrite的更多相关文章

  1. Java并发编程:CopyOnWrite容器的实现

    Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...

  2. Java并发集合的实现原理

    本文简要介绍Java并发编程方面常用的类和集合,并介绍下其实现原理. AtomicInteger 可以用原子方式更新int值.类 AtomicBoolean.AtomicInteger.AtomicL ...

  3. java并发容器类

    本文主要介绍java并发容器相关实现类,collections节点下接口方法介绍. Queue Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是Blocking ...

  4. Java并发编程:并发容器之CopyOnWriteArrayList(转载)

    Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...

  5. Java并发编程:并发容器之CopyOnWriteArrayList

    转载: Java并发编程:并发容器之CopyOnWriteArrayList Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个 ...

  6. Java 并发基础

    Java 并发基础 标签 : Java基础 线程简述 线程是进程的执行部分,用来完成一定的任务; 线程拥有自己的堆栈,程序计数器和自己的局部变量,但不拥有系统资源, 他与其他线程共享父进程的共享资源及 ...

  7. java并发程序——并发容器

    概述 java cocurrent包提供了很多并发容器,在提供并发控制的前提下,通过优化,提升性能.本文主要讨论常见的并发容器的实现机制和绝妙之处,但并不会对所有实现细节面面俱到. 为什么JUC需要提 ...

  8. Java 并发集合的实现原理

    http://www.codeceo.com/article/the-implementation-principle-of-java-concurrent-collection.html 阿凡卢   ...

  9. 【转】Java并发编程:并发容器之CopyOnWriteArrayList

    Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候,才会真正把内容Copy出去形成一个新的内容然后再改, ...

随机推荐

  1. 01 . Redis简介及部署主从复制

    简介 Remote Dictionary Server, 翻译为远程字典服务, Redis是一个完全开源的基于Key-Value的NoSQL存储系统,他是一个使用ANSIC语言编写的,遵守BSD协议, ...

  2. 从 React 架构开始讲解 useState、useEffect 编程设计

    随着前端开发复杂度增加,原生开发模式显得越来越笨重,前端框架也层出不穷. MVC 和 MVVM MVC MVC是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计 ...

  3. 前端HTML div标签的用法 盒子模型

    盒子模型 边框 border -外边距 margin- 内容与边框距离padding[会撑大div边框]- 宽width-高height. div的奇特玩法 1.把div弄成圆形 [css设置bord ...

  4. 使用turtle库绘制奥运五环

    import turtle as t t.setup(600,600,50,50) t.pensize(3) t.pencolor("red") t.penup() t.pendo ...

  5. Java实现 LeetCode 336 回文对

    336. 回文对 给定一组唯一的单词, 找出所有不同 的索引对(i, j),使得列表中的两个单词, words[i] + words[j] ,可拼接成回文串. 示例 1: 输入: ["abc ...

  6. Java实现 洛谷 P1618 三连击(升级版)

    import java.util.Arrays; import java.util.Scanner; public class Main { private static Scanner cin; p ...

  7. Java实现 蓝桥杯 历届试题 横向打印二叉树

    问题描述 二叉树可以用于排序.其原理很简单:对于一个排序二叉树添加新节点时,先与根节点比较,若小则交给左子树继续处理,否则交给右子树. 当遇到空子树时,则把该节点放入那个位置. 比如,10 8 5 7 ...

  8. Java实现 蓝桥杯 历届试题 错误票据

    问题描述 某涉密单位下发了某种票据,并要在年终全部收回. 每张票据有唯一的ID号.全年所有票据的ID号是连续的,但ID的开始数码是随机选定的. 因为工作人员疏忽,在录入ID号的时候发生了一处错误,造成 ...

  9. 【Spring注解驱动开发】聊聊Spring注解驱动开发那些事儿!

    写在前面 今天,面了一个工作5年的小伙伴,面试结果不理想啊!也不是我说,工作5年了,问多线程的知识:就只知道继承Thread类和实现Runnable接口!问Java集合,竟然说HashMap是线程安全 ...

  10. 举一个有趣的例子,让你轻松搞懂JVM内存管理

    目录 前言 例子 源码 输出 图解 深入分析 学以致用 写在最后 前言 在JAVA虚拟机内存管理中,堆.栈.方法区.常量池等概念经常被提到,对理论知识的理解也常常停留在字面意思上,比如说堆内存中存放对 ...