简体   繁体   English

哪些 Java 集合是同步的(线程安全的),哪些不是?

[英]Which Java Collections are synchronized(thread safe), which are not?

Which Java Collections are synchronized, which are not?哪些 Java 集合是同步的,哪些不是?

Example: HashSet is not synchronized示例:HashSet 不同步

There are three groups of Collections.共有三组集合。

  • Java 1.0 collections which mostly legacy classes. Java 1.0 集合主要是遗留类。 This includes Hashtable, Vector, Stack.这包括哈希表、向量、堆栈。 These are synchronized but I don't recommend you use them.这些是同步的,但我不建议您使用它们。 Properties is perhaps one exception, but I wouldn't use it in a multi-threaded context.属性可能是一个例外,但我不会在多线程上下文中使用它。
  • Java 1.2 collections added in 1998 which largely replaced these collection are not synchronized, but can be synchronized using Collections.synchronizedXxx() methods 1998 年添加的 Java 1.2 集合在很大程度上取代了这些集合不是同步的,但可以使用Collections.synchronizedXxx()方法进行同步
  • Java 5.0 concurrency collections added in 2004 support lock free, thread safe collections. 2004 年添加的 Java 5.0 并发集合支持无锁、线程安全的集合。

In short, none of the collections I would recommend you use are synchronized.简而言之,我建议您使用的所有集合都不是同步的。

Thread safe Collections -线程安全集合 -

  1. ConcurrentHashMap并发哈希映射

Thread safe without having to synchronize the whole map Very fast reads while write is done with a lock No locking at the object level Uses multitude of locks.线程安全,无需同步整个地图 使用锁完成写入时读取速度非常快 在对象级别没有锁定 使用多个锁。

  1. SynchronizedHashMap同步哈希映射

Object level synchronization Both read and writes acquire a lock Locking the collection has a performance drawback May cause contention对象级同步 读写都获取锁 锁定集合有性能缺陷 可能导致争用

  1. Vector向量

  2. HashTable哈希表

  3. CopyOnWriteArrayList复制写入数组列表

  4. CopyOnWriteArraySet复制写入数组集

  5. Stack

Rest all are not thread safe其余的都不是线程安全的

You can get a synchronized version of a Java Collection with您可以获得 Java Collection的同步版本

Collections.synchronizedCollection(Collection<T> c)

[ javadoc ] [ javadoc ]

Easy answer: not a single implementation of Collection is synchronized because synchronized is not a class property, it is only applicable to methods and blocks.简单回答:没有一个Collection实现是同步的,因为synchronized不是类属性,它只适用于方法和块。

I guess, you want to know which implementations are thread safe , which classes from the java collection framework can safely be used in a multithreaded environment.我想,您想知道哪些实现是线程安全的,哪些来自 java 集合框架的类可以安全地用于多线程环境中。

The information is always included in the javadoc ( like here: Arraylist - which is not thread safe)该信息始终包含在 javadoc 中( 例如:Arraylist - 这不是线程安全的)

ArrayList, LinkedList, HashSet,LinkedHashset and TreeSet in Collection Interface and HashMap,LinkedHashMap and Treemap are all non-synchronized . Collection 接口中的ArrayList、LinkedList、HashSet、LinkedHashset 和TreeSet 以及HashMap、LinkedHashMap 和Treemap 都是非同步的

Vector in Collection Interface is Synchronized集合接口中的向量是同步的

The previous example is totally wrong.前面的例子是完全错误的。

First of all, you are not accessing from different threads the list that you just synchronized, you have no prove that the synchronization is being performed properly, you cannot prove that the add process is atomic.首先,您没有从不同的线程访问您刚刚同步的列表,您无法证明同步正在正确执行,您无法证明添加过程是原子的。 Second the synchronized clause over the list itself is a bad practice, you don't know if the optimizer will use an item in the list to do the synchronization, leading to an unexpected behavior.其次,列表本身上的同步子句是一种不好的做法,您不知道优化器是否会使用列表中的项目进行同步,从而导致意外行为。 Also, what you're synchronizing is the access to the elements in the list read/write, not the list itself.此外,您正在同步的是对列表中元素的读取/写入访问,而不是列表本身。 Take out the Collections.synchronized and see the output.取出 Collections.synchronized 并查看输出。 Try many times.多试几次。 Please take following example:请举以下例子:

class ProcessSomething {
    private List<Integer> integerList = Collections.synchronizedList(new ArrayList<>());
    private void calculate() {
        for (int i = 0; i < 10000; i++) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException ex) {
                Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
            }
            integerList.add(new Random().nextInt(100));
        }
    }
    private void calculate2() {
        for (int i = 0; i < 10000; i++) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException ex) {
                Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
            }
            integerList.add(new Random().nextInt(100));
        }
    }
    public void process() {
        Long start = System.currentTimeMillis();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                calculate();
            }
        });
        t1.start();
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                calculate2();
            }
        });
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException ex) {
            Logger.getLogger(ProcessSomething.class.getName()).log(Level.SEVERE, null, ex);
        }
        Long end = System.currentTimeMillis();
        System.out.println("Duration: " + (end - start));
        System.out.println("List size: " + integerList.size());
    }
}
public class App {
    public static void main(String[] args) {
        new ProcessSomething().process();
    }
}

All collection classes (except Vector and Hashtable) in the java.util package are not thread-safe. java.util 包中的所有集合类(Vector 和Hashtable 除外)都不是线程安全的。 The only two legacy collections are thread-safe: Vector and Hashtable.仅有的两个遗留集合是线程安全的:Vector 和 Hashtable。 WHY?为什么? Here's the reason: Synchronization can be very expensive!原因如下:同步可能非常昂贵! You know, Vector and Hashtable are the two collections exist early in Java history, and they are designed for thread-safe from the start (if you have chance to look at their source code, you will see their methods are all synchronized!).你知道,Vector 和 Hashtable 是 Java 历史早期存在的两个集合,它们从一开始就是为线程安全而设计的(如果你有机会查看它们的源代码,你会发现它们的方法都是同步的!)。 However, they quickly expose poor performance in multi-threaded programs.然而,它们很快暴露了多线程程序的性能不佳。 As you may know, synchronization requires locks which always take time to monitor, and that reduces the performance.您可能知道,同步需要锁,这总是需要时间来监控,这会降低性能。 That's why the new collections (List, Set, Map, etc) provide no concurrency control at all to provide maximum performance in single-threaded applications.这就是新集合(List、Set、Map 等)根本不提供并发控制以在单线程应用程序中提供最大性能的原因。

synchronize makes performance lower.同步使性能降低。 of course, Java collection is not synchronized.当然,Java集合不是同步的。 but Java provides a Synchronization Wrappers to synchronize Java Collection see link但是 Java 提供了一个 Synchronization Wrappers 来同步 Java Collection 见链接

for example:


    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Iterator;
    import java.util.List;

    public class SynchronizedListExample {

        public static void main(String[] args) {

            List<String> syncList = Collections.synchronizedList(new ArrayList<String>());

            syncList.add("one");//no need to synchronize here
            syncList.add("two");
            syncList.add("three");
            String st = syncList.get(0); //it is ok here => no need to synchronize

            // when iterating over a synchronized list, we need to synchronize access to the synchronized list
           //because if you don't synchronize here, synchList maybe be changed during iterating over it
            synchronized (syncList) {
                Iterator<String> iterator = syncList.iterator();
                while (iterator.hasNext()) {
                    System.out.println("item: " + iterator.next());
                }
            }

        }

    }

import java.util.Collections;导入 java.util.Collections; //Import this //导入这个

List<String> syncList = Collections.synchronizedList(new ArrayList<String>());

This is how you can synchronise a list in java.这就是您如何在 Java 中同步列表。

Thread safe Collections线程安全集合

  • Legacy - Vector (parent is List ) and Hashtable (parent is Map )传统 - Vector (父级为List )和Hashtable (父级为Map
  • Synchronized collections uses synchronized monitor.同步集合使用synchronized监视器。 Collections.synchronized , Collections.synchronizedList() , Collections.synchronizedSortedMap() , Collections.synchronizedSet() ... Collections.synchronized , Collections.synchronizedList() , Collections.synchronizedSortedMap() , Collections.synchronizedSet() ...
  • Concurrent collections(Java 5)并发集合(Java 5)
    • Copy-On-Write(COW) - has better performance then Synchronized collections, but has a bigger memory footprint. Copy-On-Write(COW) - 比同步集合具有更好的性能,但具有更大的内存占用。 New copy of array is created when you modify it(add, set, remove).修改数组时会创建新的数组副本(添加、设置、删除)。 It is a good variant for multi read operations and rear modifications.它是多读操作和后修改的一个很好的变体。 CopyOnWriteArrayList , CopyOnWriteArraySet CopyOnWriteArrayList , CopyOnWriteArraySet
    • Compare-And-Swap(CAS) [About] - ConcurrentLinkedQueue , ConcurrentSkipListMap Compare-And-Swap(CAS) [关于] - ConcurrentLinkedQueue , ConcurrentSkipListMap
    • Lock based - ConcurrentHashMap , BlockingQueue descendants基于Lock - ConcurrentHashMap , BlockingQueue后代

我猜集合 API 的每个实现都写在文档中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM