Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is constructor-copy of a synchronized Set thread safe?

Tags:

java

The easiest way to get a synchronized version of a java.util.Set would be using Collections.synchronizedSet() like this:

Set mySyncSet = Collections.synchronizedSet(new HashSet());

The Java API says about this new object that:

It is imperative that the user manually synchronize on the returned set when iterating over it

My question is, if I create a copy of this Set using a copy constructor like this:

Set mySetCopy = new HashMap(mySyncSet);

Wil it be thread-safe? (isn't HashMap constructor using iteration to get members of Set after all?) or should I manually synchronize the operation like this?:

Set mySetCopy;

synchronized(mySyncSet) {
    mySetCopy = new HashMap(mySyncSet);
}
like image 436
morgano Avatar asked Jan 13 '23 22:01

morgano


1 Answers

Lets take a look at the code:

public HashSet(Collection<? extends E> c) {
    map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
    addAll(c);
}

So that just calls addAll,

public boolean addAll(Collection<? extends E> c) {
    boolean modified = false;
    for (E e : c)
        if (add(e))
            modified = true;
    return modified;
}

So this loops over the Collection you give it.

The answer is therefore no, constructor copy is not thread safe.

You need to use your second option and do a explicit synchronized on the Set before passing it into the constructor.

like image 197
Boris the Spider Avatar answered Jan 30 '23 00:01

Boris the Spider