`
MauerSu
  • 浏览: 509658 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

CopyOnWriteArrayList类set方法疑惑?

 
阅读更多
源:http://ifeve.com/copyonwritearraylist-set/
评:
在淘宝内网有位同事提了一个很好的问题,大家能否帮忙解答下?

在CopyOnWriteArrayList类的set方法中有一段setArray(elements)代码,实际上这段代码并未对elements做任何改动,实现的volatile语意并不对CopyOnWriteArrayList实例产生任何影响,为什么还是要保留这行语句?见以下代码红体部分:

01
/** The array, accessed only via getArray/setArray. */
02
private volatile transient Object[] array;
03

04
/**
05
* Replaces the element at the specified position in this list with the
06
* specified element.
07
*
08
* @throws IndexOutOfBoundsException {@inheritDoc}
09
*/
10
public E set(int index, E element) {
11
    final ReentrantLock lock = this.lock;
12
    lock.lock();
13
    try {
14
        Object[] elements = getArray();
15
        E oldValue = get(elements, index);
16

17
        if (oldValue != element) {
18
            int len = elements.length;
19
            Object[] newElements = Arrays.copyOf(elements, len);
20
            newElements[index] = element;
21
            setArray(newElements);
22
        } else {
23
            // Not quite a no-op; ensures volatile write semantics
24
            setArray(elements);
25
        }
26
        return oldValue;
27
    } finally {
28
        lock.unlock();
29
    }
30
}
31

32
/**
33
* Sets the array.
34
*/
35
final void setArray(Object[] a) {
36
    array = a;
37
}
38

39
/**
40
* Gets the array.  Non-private so as to also be accessible
41
* from CopyOnWriteArraySet class.
42
*/
43
final Object[] getArray() {
44
    return array;
45
}
===================
我想我可能找到这个问题的答案了,虽然在set方法的的API文档中没有描述它包含的内存语义。但在jdk有个地方描述到了:http://docs.oracle.com/javase/7/docs/api/ 的最下方的几条,摘录过来如下:

The methods of all classes in java.util.concurrent and its subpackages extend these guarantees to higher-level synchronization. In particular:Actions in a thread prior to placing an object into any concurrent collection happen-before actions subsequent to the access or removal of that element from the collection in another thread.

中文版API中是这样描述的:

java.util.concurrent 中所有类的方法及其子包扩展了这些对更高级别同步的保证。尤其是: 线程中将一个对象放入任何并发 collection 之前的操作 happen-before 从另一线程中的 collection 访问或移除该元素的后续操作。

CopyOnWriteArrayList作为java.util.concurrent包中的类之一,当然它也要遵守这个约定。所以才在else里面加了一个 setArray(elements);来保证hb关系。


Ticmy
2013/01/16 1:01下午
登录以回复 引用
链接贴错了:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html


Ticmy
2013/01/16 1:25下午
登录以回复 引用
这个hb意义何在?如下例子:a为非volatile的某基本类型变量,coal为CopyOnWriteArrayList对象
t1:
x:a = calValue;
y:coal.set….
———————
t2:
m:coal.get…
n:int tmp = a;

假设存在以上场景,如果能保证只会存在这样的轨迹:x,y,m,n.根据上述java API文档中的约定有hb(y,m),根据线程内的操作相关规定有hb(x,y),hb(m,n),根据hb的传递性读写a变量就有hb(x,n),所以t1对a的写操作对t2中a的读操作可见。如果CopyOnWriteArrayList的set的else里没有setArray(elements)的话,hb(y,m)就不再有了,上述的可见性也就无法保证。


michaelchan
2016/02/18 10:52上午
登录以回复 引用
的确是这样,实际上不是为了保证COW List本身的可见性,而是保证外部的非volatile变量的HB。

参考:
http://stackoverflow.com/questions/28772539/why-setarray-method-call-required-in-copyonwritearraylist
分享到:
评论

相关推荐

    java并发容器CopyOnWriteArrayList实现原理及源码分析

    Java并发容器CopyOnWriteArrayList实现原理及源码分析 Java并发容器CopyOnWriteArrayList是Java并发包中提供的一个并发容器,实现了线程安全且读操作无锁的ArrayList,写操作则通过创建底层数组的新副本来实现。...

    java 运用集的相关类(Set)

    5. CopyOnWriteArraySet:这是一个线程安全的Set实现,它基于CopyOnWriteArrayList。适用于读多写少的并发场景,迭代器不会抛出ConcurrentModificationException。 在`MySetClass.java`源代码中,可能包含了创建和...

    java遍历时可修改的容器CopyOnWriteArrayList.html

    java遍历时可修改的容器CopyOnWriteArrayList

    Java的CopyOnWriteArrayList功能详解,及无法保证数据是实时同步.docx

    为了避免这种情况,可以使用`Iterator`进行迭代并使用`Iterator`的`remove()`方法,或者使用线程安全的集合,如`CopyOnWriteArrayList`,因为其迭代器允许并发修改,不会抛出此异常。 在选择线程安全的集合类时,...

    Java源码解析CopyOnWriteArrayList的讲解

    set方法用于修改集合中的元素,它也需要加锁,以确保写操作的线程安全。在set操作中,CopyOnWriteArrayList会创建一个新的array副本,并将元素修改到新的array中,然后将新的array赋值给老的array。 remove方法 ...

    java集合-CopyOnWriteArrayList的使用

    在Java中,CopyOnWriteArrayList(写入时复制数组列表)是线程安全的集合类,它实现了List接口,并使用了"写入时复制"的策略来保证线程安全性。 CopyOnWriteArrayList的主要特点是:在进行修改操作(例如添加、修改...

    第三章 CopyOnWriteArrayList源码解析1

    CopyOnWriteArrayList是Java集合框架中的一个特殊列表,位于`java.util.concurrent`包下,专为并发编程场景设计。它的核心特性在于写时复制(Copy-On-Write)策略,这使得它在多线程环境下提供了良好的性能表现。当...

    基于CopyOnWriteArrayList并发容器(实例讲解)

    CopyOnWriteArrayList的add方法的实现是需要加锁的,否则多线程写的时候会Copy出N个副本出来。读的时候不需要加锁,如果读的时候有多个线程正在向CopyOnWriteArrayList添加数据,读还是会读到旧的数据,因为写的时候...

    Java 多线程与并发(14-26)-JUC集合- CopyOnWriteArrayList详解.pdf

    `CopyOnWriteArrayList`是一种线程安全的集合类,它是`ArrayList`的一种特殊版本,主要通过复制底层数组的方式来保证线程安全性。这种策略通常被称为“写时复制”(Copy-On-Write,简称COW)。 #### 二、Fail-fast...

    Java_Collection_List-Set-Map.zip_list set map

    - 如果需要线程安全,可以使用CopyOnWriteArrayList,ConcurrentSkipListSet和ConcurrentHashMap等并发集合类。 7. **容量与扩容**: - List和Set在添加元素时,如果达到当前容量,会自动扩容。ArrayList的默认...

    CopyOnWriteArrayList.uml

    目前上传的是CopyOnWriteArrayList.uml类图,包含该类的各个extends、implements的接口或者类

    对Java中Set的深入研究.pdf

    - `CopyOnWriteArraySet`:这个类基于`CopyOnWriteArrayList`实现,适用于并发环境,它在读多写少的情况下性能较好,因为读操作不会阻塞写操作。 - `HashSet`:基于哈希表(HashMap)实现,插入和查找的平均时间...

    CopyOnWriteArrayList是怎么实现写有锁,读无锁,读写之间不堵塞的?(加强版读写分离源码剖析)

    CopyOnWriteArrayList是Java集合框架中的一个重要类,它是ArrayList的线程安全版本,特别适合于读多写少的并发场景。这个类通过一种称为“写时复制”(Copy-On-Write)的技术实现了读写分离,确保了在进行写操作时不会...

    Java多线程-知识点梳理和总结-超详细-面试知识点.docx

    7. 什么是CopyOnWriteArrayList?CopyOnWriteArrayList的作用是什么? 8. 什么是Thread安全?Thread安全的设计理念是什么? 9. 什么是CAS操作?CAS操作的作用是什么? 10. JDK 1.7和JDK 1.8的差异是什么? 本文从...

    wuhaocn#guide-doc#并发容器之CopyOnWriteArrayList1

    1. CopyOnWriteArrayList的简介 2. COW的设计思想 3. CopyOnWriteArrayList的实现原理 4. 总结 2.读线程间

    Java concurrency集合之 CopyOnWriteArrayList_动力节点Java学院整理

    CopyOnWriteArrayList提供了多种构造方法和操作方法,包括: * 创建一个空列表:CopyOnWriteArrayList() * 创建一个按collection的迭代器返回元素的顺序包含指定collection元素的列表:CopyOnWriteArrayList...

    java中循环遍历删除List和Set集合中元素的方法(推荐)

    这两个类在内部创建副本进行修改,从而允许在遍历时安全地修改集合,但请注意,这种方法不适合频繁的修改操作,因为它会创建新的集合实例,可能导致内存开销增加。 4. **使用流(Stream)操作(Java 8及以上版本)** ...

    Java中CopyOnWriteArrayList的使用

    java中,List在遍历的时候,如果被修改了会抛出java.util.ConcurrentModificationException错误。  看如下代码: import java.util.ArrayList; import java.util.List; public class Resource3 { ...

    30个Java经典的集合面试题!.zip

    它包括List、Set、Queue等接口以及ArrayList、LinkedList、HashSet、HashMap等实现类。 2. **ArrayList和LinkedList的区别是什么?** ArrayList基于动态数组实现,提供随机访问但插入和删除元素较慢。LinkedList...

Global site tag (gtag.js) - Google Analytics