Enosh Bansode
Enosh Bansode

Reputation: 1778

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

Which Java Collections are synchronized, which are not?

Example: HashSet is not synchronized

Upvotes: 38

Views: 113914

Answers (10)

Varun Chandran
Varun Chandran

Reputation: 671

import java.util.Collections; //Import this
    
List<String> syncList = Collections.synchronizedList(new ArrayList<String>());

This is how you can synchronise a list in java.

Upvotes: 0

yoAlex5
yoAlex5

Reputation: 34245

Java Thread safe Collections

  • Legacy - Vector(parent is List) and Hashtable(parent is Map)
  • Synchronized collections uses synchronized monitor. Collections.synchronized, Collections.synchronizedList(), Collections.synchronizedSortedMap(), Collections.synchronizedSet()...
  • Concurrent collections(Java 5)
    • Copy-On-Write(COW) - has better performance than Synchronized collections, but has a bigger memory footprint. 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
    • Compare-And-Swap(CAS)[About] - ConcurrentLinkedQueue, ConcurrentSkipListMap
    • Lock based - ConcurrentHashMap, BlockingQueue descendants

Upvotes: 4

Ujjwal Choudhari
Ujjwal Choudhari

Reputation: 421

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

Upvotes: 30

Apurva Dwivedi
Apurva Dwivedi

Reputation: 41

All collection classes (except Vector and Hashtable) in the java.util package are not thread-safe. The only two legacy collections are thread-safe: Vector and 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!). 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.

Upvotes: 4

Oscar
Oscar

Reputation: 31

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. 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();
    }
}

Upvotes: 3

HungNM2
HungNM2

Reputation: 3425

synchronize makes performance lower. of course, Java collection is not synchronized. but Java provides a Synchronization Wrappers to synchronize Java Collection see link

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());
                }
            }

        }

    }

Upvotes: 1

dgl viru
dgl viru

Reputation: 177

ArrayList, LinkedList, HashSet,LinkedHashset and TreeSet in Collection Interface and HashMap,LinkedHashMap and Treemap are all non-synchronized.

Vector in Collection Interface is Synchronized

Upvotes: 6

Peter Lawrey
Peter Lawrey

Reputation: 533530

There are three groups of Collections.

  • Java 1.0 collections which mostly legacy classes. 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
  • Java 5.0 concurrency collections added in 2004 support lock free, thread safe collections.

In short, none of the collections I would recommend you use are synchronized.

Upvotes: 19

Andreas Dolk
Andreas Dolk

Reputation: 114777

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.

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.

The information is always included in the javadoc (like here: Arraylist - which is not thread safe)

Upvotes: 8

MarcoS
MarcoS

Reputation: 13564

You can get a synchronized version of a Java Collection with

Collections.synchronizedCollection(Collection<T> c)

[javadoc]

Upvotes: 15

Related Questions