美文网首页Java学习笔记
集合的线程安全

集合的线程安全

作者: 蜗先生 | 来源:发表于2017-06-05 23:49 被阅读183次

线程安全的集合:Vector、HashTable
线程不安全的集合:ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap

线程不安全的集合如何保证线程安全?
用Collections工具类中的同步方法SynchronizedList()、SynchronizedSet()、SynchronizedMap()可以保证List、Set、Map集合变成线程安全的集合。线程安全集合中的方法被synchronized修饰从而保证了线程安全,通过同步方法变成线程安全的集合是对集合原有的方法加了synchronized块保证线程安全。

用法:
static List<T> synchronizedList(List<T> list)
static Set<T> synchronizedSet(Set<T> set)
static Map<T> synchronizedMap(Map<T> map)

例:

List<String> list = new List<String>();
List<String> synList = list.SynchronizedList(list);

线程安全集合是否一定会都会线程安全?
不是

不论是线程安全集合还是同步方法保证的线程安全的集合,都是对集合中的方法加同步锁,对于加了同步锁的符合运算不能保证线程安全,还是需要手动加同步锁。

例:

public void run() {
    for (int i = 0; i < 5; i++) {
        if (synList.size() < 3) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synList.add(i);
            System.out.println(i);
        }
    }
}

上例中synList.size()和synList.add()都是同步的,但是复合操作不能保证线程安全必须要在if语句块前后加synchronized同步锁。
结果:0 0 1 1

关于迭代的同步问题:
1)之前了解到迭代器过程中不能有集合长度的变化,也就是说不能有add()和remove()操作,否则会出现ConcurrentModificationException异常。另一方面,一个集合迭代过程中,如果其他线程改变集合中的元素,会影响迭代的效果。
为防止多线程过程中一个集合的迭代,其他线程执行add()、remove()、set(),多线程中线程安全的集合的迭代器必须要加synchronized同步锁。获取迭代器和while循环都要放在同步锁内,且同步锁的锁对象必须是与add()、remove()、set()同步锁相同的对象,经过对源码的查看,也就是同步之后的集合对象。

例:

//Must Object on which to synchronize.
synchronized (synList) {
    //Must be in synchronized block
    Iterator<Integer> it = synList.iterator();
    while (it.hasNext()) {
        System.out.println(it.next());
    }
}

2)增强for循环遍历与迭代器相同,多线程中也会出现ConcurrentModificationException异常。

例:

synchronized (synList) {
    for(Integer i : synList){
        System.out.println(it.next());
    }
}

3)还有第三种遍历方式,普通for循环遍历,这个遍历不会出现异常。遍历过程中其他线程改变集合元素会对遍历产生影响。

例:

synchronized (synList) {
    for(int i = 0; i < synList.size(); i++){
        System.out.println(synList.get(i));
    }
}

4)listIterator遍历器也可以实现对集合的遍历的同时改变集合的长度,所以不会出现ConcurrentModificationException异常,不需要同步锁,listIterator中原有的方法add()和remove()可以实现遍历的同时添加和删除元素的操作。

相关文章

  • 集合的线程安全

    线程安全的集合:Vector、HashTable线程不安全的集合:ArrayList、LinkedList、Has...

  • 常用集合及源码解读

    在工作中集合的使用非常广泛,集合是分线程安全和线程不安全的。在多线程环境下,是需要使用线程安全的集合的,否则就会...

  • ConcurrentHashMap源码设计分析

    二、线程安全(Thread-safe)的集合对象:● Vector 线程安全● HashTable 线程安全● S...

  • Java 集合

    1、java集合分类 线程安全的集合对象:Vector :是ArrayList的线程安全的实现HashTableS...

  • 线程安全集合

    早期线程安全的集合 我们先从早期的线程安全的集合说起,它们是Vector和HashTable VectorVect...

  • 「Java面试必会」谈谈并发包java .util.concur

    说到集合,就知道有的集合类并不是线程安全的,那Java中怎么保证集合是线程安全的? java .util.conc...

  • 并发总结(下)

    7.3.7 线程安全集合类概述 重点介绍 java.util.concurrent.* 下的线程安全集合类,可以发...

  • 十二、线程安全的集合

    十二、线程安全的集合 除了使用锁来保护共享数据结构,也可以直接使用一些实现了线程安全的对象 常见的线程安全集合 线...

  • 关于Java中的 CopyOnWriteArraySet

    最近做的课程设计中用到了Java线程安全的集合类,因此关于对Java线程安全集合类的理解做个简单记录。Java集合...

  • Vector与ArrayList,HashMap与HashTab

    开发中哪些地方遇到线程安全的: 集合有些是线程安全的有些是线程不安全的。 Vector与ArrayList 区别:...

网友评论

    本文标题:集合的线程安全

    本文链接:https://www.haomeiwen.com/subject/tpiifxtx.html