精华内容
下载资源
问答
  • 线程安全集合
    千次阅读
    2022-01-20 15:53:57

    List中:

    Vector:线程安全,是长度可变的数组

    ArrayList:线程不安全的,他的线程安全替代是Vector

    如何将 ArrayList升级为线程安全的List

    ArrayList升级为线程安全的List 实例

      具体实现代码如下,使用Collections工具类进行升级,如下:

    package com.yang.concurrent;
     
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
     
    /**
     * 本实例演示ArrayList升级为线程安全的List
     */
    public class SyncArrayList {
        public static void main(String[] args) {
            List<Integer> list= Collections.synchronizedList(new ArrayList<>());
            list.add(1);
            System.out.println(list.get(0));
        }
    }

    通过加锁的方式进行:

     由此我们可知:ArrayList包装成线程安全的List后,和Vector的性能差不多。

    Map:

    HashMap:线程不安全的,他的线程安全的替代是HashTable

    或者是currenthashmap,也是线程安全的 

    HashTable:HashTable是线程安全的,它给几乎所有public方法都加上了synchronized关键字

    更多相关内容
  • c#官方线程安全集合源码,concurrentBag concurrentqueue,concurrentset,concurrentDictionary,concurrentSet等
  • Java多线程安全集合

    2017-03-17 10:24:42
    Java的多种多线程安全集合的介绍和示例代码
  • Java线程安全集合总结

    千次阅读 2021-10-13 17:48:00
    从图中可以看出,这些线程安全集合主要分为两类,以Concurrent开头的集合类和以CopyOnWrite开头的集合类。 1、以Concurrent开头的集合类,可以支持多个线程并发写入访问,写入操作都是线程安全的,读取操作不必...

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/120749064
    本文出自【赵彦军的博客】

    Java线程安全StampedLock
    Java线程安全Lock、ReentrantLock、ReentrantReadWriteLock
    Java线程安全集合总结
    Java原子操作Atomic

    从Java5开始,在Java.util.concurrent包下提供了大量支持高效并发访问的集合接口和实现类,如下图:

    在这里插入图片描述

    从图中可以看出,这些线程安全的集合主要分为两类,以Concurrent开头的集合类和以CopyOnWrite开头的集合类。

    1、以Concurrent开头的集合类,可以支持多个线程并发写入访问,写入操作都是线程安全的,读取操作不必锁定,采用更复杂的算法保证永不会锁住整个集合,因此在并发写入时有较好的性能。
    ConcurrentLinkedQueue实现多线程高效、无须等待的访问,不能使用null元素。
    ConcurrentLinkedQueue和ConcurrentHashMap最好不要使用迭代器,因为迭代器可能不能反映出创建迭代器后所做的修改,但程序不会出现异常。

    2、以CopyOnWrite开头的集合类,采用复制底层数组的方式来实现写操作,读时无须加锁,对复制的新数组进行写操作,所以线程安全,频繁的复制数组,性能比较差,但读操作因为没有加锁和阻塞就很快、很安全

    线程安全的集合

    val list = CopyOnWriteArrayList<String>()
    val map = ConcurrentHashMap<String, String>()
    val set = CopyOnWriteArraySet<String>()
    

    把不安全的集合转化成线程安全的

    • List
    val unsafeList = ArrayList<String>()
    //方式一
    val list = Collections.synchronizedList(unsafeList)
    //方式二
    val list = CopyOnWriteArrayList(unsafeList)
    
    • Map
    val unsafeMap = HashMap<String, String>()
    //方式一
    val map = Collections.synchronizedMap(unsafeMap)
    //方式二
    val map = ConcurrentHashMap(unsafeMap)
    
    • Set
    val unsafeSet = HashSet<String>()
    //方式一
    val set = Collections.synchronizedSet(unsafeSet)
    //方式二
    val set = CopyOnWriteArraySet(unsafeSet)
    
    展开全文
  • 主要介绍了详解java各种集合线程安全,小编觉得挺不错的,这里分享给大家,供需要的朋友参考。
  • CopyOnWrite线程安全集合

    千次阅读 2022-01-02 20:44:56
    其实现线程安全的核心思想是读写分离,即在写的时候,将底层的数组拷贝一份,然后修改拷贝的数组,再将修改后的数组通过原子操作的方式赋值给底层数组,以实现线程安全 二、CopyOnWriteArrayList 2-1 底层结构

    一、CopyOnWrite集合简介

    CopyOnWrite集合包括CopyOnWriteArrayList,CopyOnWriteSet和CopyOnWriteHashMap,但CopyOnWriteHashMap使用较少,并发环境大多采用性能更高的cpncurrentHashMap。其实现线程安全的核心思想是读写分离,即在写的时候,将底层的数组拷贝一份,然后修改拷贝的数组,再将修改后的数组通过原子操作的方式赋值给底层数组,以实现线程安全

    二、CopyOnWriteArrayList

    2-1 底层结构

        final transient ReentrantLock lock = new ReentrantLock();
    
        /** The array, accessed only via getArray/setArray. */
        private transient volatile Object[] array;

            可以看到CopyOnArrayList底层的实现机理是一个volatile修饰的数组,意味着这个数组的修改对于其他线程是具有可见性的,进而保证了读写时的线程安全问题。

            lock是用来确保写写线程之间的安全性的,设置增删改的操作均需要加锁

    2-2 get

    public E get(int index) {
            return get(getArray(), index);
        }
    
    
    private E get(Object[] a, int index) {
            return (E) a[index];
        }
    

    与ArrayList类似,是获取数组中索引为index的元素。

    2-3 add

    public boolean add(E e) {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                int len = elements.length;
                //核心代码,将原先的数组拷贝一份,但是长度为原先的长度+1
                Object[] newElements = Arrays.copyOf(elements, len + 1);
                //在len索引处设置新值
                newElements[len] = e;
                //重新设置底层数组
                setArray(newElements);
                return true;
            } finally {
                lock.unlock();
            }
        }

            可以看到,代码的核心思想就是拷贝一份elements数组,但是将长度设置为len+1,进行添加操作时,在拷贝的数组newElements中进行添加操作。待添加完成后,将element设置为newElement。

             因为读和写操作的副本并不是同一个,因此,并不会存在线程安全的问题,而element采用volatile修饰,在修改完成后,对其他线程立即可见,因此,保证了读写的线程安全问题。

            同时在添加的过程中,使用了锁,保证了写写线程之间的安全性问题。

    2-4 set

    public E set(int index, E element) {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                E oldValue = get(elements, index);
    
                if (oldValue != element) {
                    int len = elements.length;
                    Object[] newElements = Arrays.copyOf(elements, len);
                    newElements[index] = element;
                    setArray(newElements);
                } else {
                    // Not quite a no-op; ensures volatile write semantics
                    setArray(elements);
                }
                return oldValue;
            } finally {
                lock.unlock();
            }
        }

            在修改操作进行之前,首先需要比较element[index]上的值与修改后的值是否相同,若相同,则不做修改,若不同,拷贝一份数组,修改完成后,将拷贝的数组设置为element

    2-5 remove

     public E remove(int index) {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                Object[] elements = getArray();
                int len = elements.length;
                E oldValue = get(elements, index);
                int numMoved = len - index - 1;
                if (numMoved == 0)
                    setArray(Arrays.copyOf(elements, len - 1));
                else {
                    Object[] newElements = new Object[len - 1];
                    System.arraycopy(elements, 0, newElements, 0, index);
                    System.arraycopy(elements, index + 1, newElements, index,
                                     numMoved);
                    setArray(newElements);
                }
                return oldValue;
            } finally {
                lock.unlock();
            }
        }

           对于删除操作,新建一个数组,将原数组除去index索引处元素外的其他元素均拷贝到新数组中,完成删除后,将element设置为新数组。

    三、CopyOnWriteArraySet

            其底层实现机理与CopyOnArrayList相同,此处不再赘述,但set中是不能有重复元素的,因此对于set,其修改与添加操作较CopyOnWriteList有一些区别。

    3-1 add

    public boolean add(E e) {
            return al.addIfAbsent(e);
        }
    
        public boolean addIfAbsent(E e) {
            Object[] snapshot = getArray();
            //判断要插入的元素e在数组中是否存在
            return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
                addIfAbsent(e, snapshot);
        }
    //在elements[]数组的[index,fence)区间中寻找是否存在o
    private static int indexOf(Object o, Object[] elements,
                                   int index, int fence) {
            if (o == null) {
                for (int i = index; i < fence; i++)
                    if (elements[i] == null)
                        return i;
            } else {
                for (int i = index; i < fence; i++)
                    if (o.equals(elements[i]))
                        return i;
            }
            return -1;
        }

            在添加新元素e之前,先判断元素e在底层数组snapshot中是否存在,若存在,则返回false,代表添加失败,因为set中不能有重复元素,若不存在,则执行添加操作。

    private boolean addIfAbsent(E e, Object[] snapshot) {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                //获取最新的snapshot[]
                Object[] current = getArray();
                int len = current.length;
                //snapshot被其他线程修改过
                if (snapshot != current) {
                    // Optimize for lost race to another addXXX operation
                    int common = Math.min(snapshot.length, len);
                    for (int i = 0; i < common; i++)
                        if (current[i] != snapshot[i] && eq(e, current[i]))
                            return false;
                    if (indexOf(e, current, common, len) >= 0)
                            return false;
                }
                Object[] newElements = Arrays.copyOf(current, len + 1);
                newElements[len] = e;
                setArray(newElements);
                return true;
            } finally {
                lock.unlock();
            }
        }

           由于上面执行indexOf时没有进行加锁操作,在执行到addIfAbsent()方法之前,底层的数组仍然有可能被修改,因此需要再次获取最新的snapshot,若:

            1)snapshot已经被修改且包含要插入的元素e,返回false

            2)snapshot已经被修改,但并不包含e,执行插入操作。

            3)snapshot没有被修改,执行插入操作。

            插入操作的实现原理与CopyOnArrayList相同,此处不再进行赘述。

    四、CopyOnWrite的优点和缺点

    优点:

    1.实现较为简单

    2.确保线程安全

    缺点:

    1.性能较差,每次进行增删改操作时均需要使用lock

    2.在修改时,需要额外拷贝一份数组,造成系统资源的开销

    因此CopyOnWrite在执行以写为主的并发操作时,性能较差。

    展开全文
  • .NET Framework4 线程安全集合详解
  • C# 线程安全集合

    千次阅读 2019-07-05 11:56:01
    从.Net 4.0框架开始,在System.Collections.Concurrent命名空间下,增加了用于多线程协同的并发集合类(线程安全集合)。 线程安全集合: 就是当多线程访问时,采用了加锁的机制;即当一个线程访问集合时,会对这个...

    本文章仅为个人理解,如有错误请指正。

    从.Net 4.0框架开始,在System.Collections.Concurrent命名空间下,增加了用于多线程协同的并发集合类(线程安全集合)。

    线程安全集合:

    就是当多线程访问时,采用了加锁的机制;即当一个线程访问集合时,会对这个集合进行保护,其他线程不能对其访问,直到该线程操作完集合之后,其他线程才可以使用。防止出现数据不一致或者数据被污染的情况。

    只能保证集合的原子性、可见性,但是无法保证对集合操作的有序性,例如:多个线程同时将元素加入到集合,无法保证元素加入到集合的顺序,多次运行情况结果会不同。

    BlockingCollection<T>

    提供具有阻塞和限制功能的线程安全集合,实现IProducerConsumerCollection<T>接口。支持容量大小的限制和完成添加限制,当标记为完成添加后只允许移除(Take)操作,无法进行添加(Add)操作。

    BoundedCapacity:获取集合限定容量,在通过构造函数时可以指定集合的容量大小。

    IsAddingCompleted:判断是否已经标记完成添加,

    IsCompleted:判断是否标记完成添加并且为空。

    Add:将项添加到集合中。

    CompleteAdding:将集合标记为完成添加。调用该函数后IsAddingCompleted为true,如果集合中包含的项数为0,那么IsCompleted也为true。

    Take:从集合中移除一项。

    TryAdd:尝试将项加入集合

    TryTake:尝试从集合中移除项。

    ConcurrentBag<T>

    提供可供多个线程同时安全访问的无序包。对应非泛型列表List<T>。

    包(Bag)和数据上的集(Set)的区别是包可包含重复元素,而集中不能包含重复元素。

    Count:获取无序包中的元素数量

    IsEmpty:判断无序包是否为空。

    TryPeek:从无序包中获取一个元素,但不进行移除。

    TryTask:从无序包获取一个元素并移除。

    ConcurrentDictionary<TKey,TValue>

    提供可供多线程同时访问的键值对的线程安全集合,对应Dictionary<TKey, TValue>。

    IsEmpty:判断字典是否为空。

    AddOrUpdate:将键值对添加到字典中,如果Key值已经存在,则更新Value值。

    Clear:将所有键值对从字典中移除。

    GetOrAdd:如果键不存在,则将键值对添加到字典中并返回Value值,如果键已经存在,则返回现有值,不会更新现有值。

    TryUpdate:尝试更新键对应的Value值。

    ConcurrentQueue<T>

    队列,提供线程安全的先进先出(FIFO)集合,对应Queue<T>。

    Enqueue:将对象添加到队列末尾处。

    TryDequeue:尝试移除并返回位于队列开头处的对象。

    TryPeek:尝试返回队列开头处的对象但不将其移除。

    ConcurrentStack<T>

    栈,提供线程安全的后进先出(LIFO)集合,对应Stack<T>

    Push:将对象插入栈顶部。

    PushRange:将多个对象插入栈的顶部。

    TryPeek:尝试返回栈顶部的对象但不将其移除。

    TryPop:尝试弹出并返回栈顶部的对象。

    TryPopRange:尝试弹出并返回栈顶部的多个对象。

    展开全文
  • 实战系列-Java中线程安全集合类(一)

    千次阅读 2021-06-04 15:19:35
    到现在基本上支持很多的线程安全的集合类,在开发过程中,有些场景中不需要注意线程安全问题,当时在一个并发场景中就必须要使用到线程安全的集合类,那么下面就来看看在Java中比较常见的线程安全集合类以及其原理。...
  • go数据结构Go数据结构是有用的,高性能的和线程安全的Go数据结构的集合。 注意:仅在Go 1.3+上进行了测试。 增强树用于n维范围内go-datastructures中的碰撞的间隔树Go-datastructures是有用的,性能良好的和线程安全...
  • C#线程安全集合ConcurrentDictionary 这个在System.Collections.Concurrent的字典类跟字典Dictionary的使用差不多是一样的,但在多线程并发访问的时候,只能靠ConcurrentDictionary了。 这是我之前储存多个...
  • 线程安全集合对象

    千次阅读 2021-11-30 17:08:13
    从.Net 4.0框架开始,在System.Collections.Concurrent命名空间下,增加了用于多线程协同的并发集合类(线程安全集合)。 ConcurrentDictionary<TKey,TValue> 提供可供多线程同时访问的键值对的线程安全集合...
  • C# 4.0 之线程安全集合

    千次阅读 2017-11-01 15:04:22
     而集合作为一种重要的临界资源,通用性更广,为了让大家更安全的使用它们,微软为我们带来了强大的并行集合:System.Collections.Concurrent里面的各位仁兄们。  首先,咱们从一个经典的问题谈起。 生产者消费...
  • 无法死锁的ReaderWriterLock和线程安全的示例集合
  • C# 的集合类型中, 都有Synchronized静态方法, 和SyncRoot实例方法 对于ArrayList以及Hashtable 集合类来讲,当需要做到线程安全的时候,最好利用其自带的属性SyncRoot 来做到,尽管...一个线程安全集合类,可为任
  • java中常见的线程安全集合

    千次阅读 2018-09-07 00:26:29
    早在jdk的1.1版本中,所有的集合都是线程安全的。但是在1.2以及之后的版本中就出现了一些线程不安全的集合,为什么版本升级会出现一些线程不安全的集合呢?因为线程不安全的集合普遍比线程安全集合效率高的多。...
  • 【Java多线程】线程安全集合

    千次阅读 2020-10-18 21:56:28
    线程安全集合 Vector Vector集合是对ArrayList集合线程安全的实现,它们两者在方法的实现上没有什么太大的区别,最大的区别就是,Vector在方法前面加上了synchronized关键字,用于保证线程安全。 【Java集合框架...
  • ConcurrentDictionary 是.NET 4.0里面新增的号称线程安全集合类。 那么自然,我们会预期ConcurrentDictionary 中的代码是线程安全的(至少几个关键方法是线程安全的). 举个例子,使用者可能会预期GetOrAdd中的...
  • 常用工具类之C++线程安全集合

    千次阅读 2016-03-10 14:19:40
    C++本身并未提供线程安全集合类,这里封装几个常用集合操作
  • Java线程安全集合是我们学习Java编程时需要掌握的一个知识点之一,因为有点繁琐,许多小伙伴不太想去总结Java线程安全集合,下面小编都已经给你整理好了,快来和小编一起看看吧!早期的线程安全集合有Vector和...
  • 线程安全集合类有哪些?

    千次阅读 2021-08-07 14:06:50
    多数情况下,我们实在单线程环境使用,或者是在方法内部,以局部变量的形式使用,一般不会出现线程安全问题。 但是当ArrayList置身于多线程环境时,很容易因为自身的fail-fast 机制抛出异常 ...
  • 线程安全集合

    2020-11-17 21:49:34
    1. 什么是线程安全 线程安全就是在并发环境下(多个线程同时执行),程序能够按照我们预期的行为去正确的执行,不会出现数据不一致或污染的情况。 2. CopyOnWriteArrayList ArrayList,相信大家都使用过,并且都知道...
  •  java.util.concurrent 包添加了多个新的线程安全集合类(ConcurrentHashMap、CopyOnWriteArrayList 和 CopyOnWriteArraySet)。这些类的目的是提供高性能、高度可伸缩性、线程安全的基本集合类型版本。  ...
  • Java线程安全集合

    千次阅读 2020-04-19 21:37:49
    1 线程安全集合 Vector 为什么Vecter是线程安全的呢?查看源代码: 从上面的代码可以看到,每个方法都加上了synchronized关键字,所以它是线程安全的。但是因为它的所有方式都加上了synchronized关键字,那么...
  • 文章目录1. 多线程环境下使用ArrayListCollections....都是线程不安全的,不过除了这些线程不安全的集合外,Java集合中还是存在一些安全的集合类的,Vector,Stack,HashTable 都是线程安全集合类,虽然这三个类是
  • 这样做是为了避免在多线程并 发add的时候,复制出多个副本出来,把数据搞乱了,导致最终的数组数据不是我们期望的。 由于所有的写操作都是在新数组进⾏的,这个时候如果有线程并发的写,则通过锁来控
  • 一、线程安全集合 二、高效的映射、集合和队列 1、ConcurrentHashMap 2、ConcurrentSkipListMap 三、写数组的拷贝 四、旧的线程安全集合 一、线程安全集合 如果多线程要并发地修改一个数据结构,例如散...
  • Java中的线程安全集合

    千次阅读 2018-08-16 14:22:41
    线程安全集合类 包括: StringBuffer: 线程安全 String: 不可变的类 , 都线程安全 Random: 线程安全 Vector: 实现了List,并且线程安全 Hashtable: ...
  • Java线程安全集合详解

    万次阅读 多人点赞 2018-03-25 18:52:32
    一、早期线程安全集合我们先从早期的线程安全集合说起,它们是Vector和HashTable1.VectorVector和ArrayList类似,是长度可变的数组,与ArrayList不同的是,Vector是线程安全的,它给几乎所有的public方法都加上...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 288,026
精华内容 115,210
关键字:

线程安全的集合

友情链接: HuaWei_TELLIN.rar