Guy
Guy

Reputation: 155

Java ConcurrentHashSet - iterating over it in a multi-threaded environment

I've seen the use cases of SynchronizedList - they state that upon iterating, even though SynchronizedList is thread-safe, we should use an iterator and a synchronized block like so -

    synchronized(myList){
    Iterator<Item> iterator = myList.iterator();
    while (iterator.hasNext())
    {
        System.out.println(iterator.next().getMessage());
    }
    }

If I use a ConcurrentHashSet for example (possible in Java 8 using newKeySet() of concurrentHashMap), in a multi-threaded environment, is it still necessary to extract an iterator and use a synchronized block? I tried testing it and it seems unnecessary but I might be missing something.

Thank you!

Upvotes: 0

Views: 3781

Answers (2)

inkognitto
inkognitto

Reputation: 74

ConcurrentHashMap.newKeySet() returns:

    /**
     * Creates a new {@link Set} backed by a ConcurrentHashMap
     * from the given type to {@code Boolean.TRUE}.
     *
     * @param <K> the element type of the returned set
     * @return the new set
     * @since 1.8
     */
    public static <K> KeySetView<K,Boolean> newKeySet() {
        return new KeySetView<K,Boolean>
            (new ConcurrentHashMap<K,Boolean>(), Boolean.TRUE);
    }

as you can see, it is backed by ConcurrentHashMap. You can use returned instance without any synchronization.

.iterator() method returns a new KeyIterator which is backed by map's Node<K,V>[] table

so, if you iterate in one particular thread that means you will see a snapshot of array of Node and each node in correct state bc Node has volatile links inside, but there is lowest chance you will see new elements added to original map bc the link iterator points is not volatile. In other words, you just iterating over a array without any guarantee if that element still exist in original map atm or some new is added there, but you can see up to date state of each node, bc:

    static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        volatile V val;
        volatile Node<K,V> next;

key is final

val is volatile

Upvotes: 3

shani klein
shani klein

Reputation: 344

For what I know -Each iterator you obtain from a ConcurrentHashMap is designed to be used by a single thread and should not be passed around.

If you try to iterate the Map with more than one thread at the same time it wont work as expected unless each of the threads uses it's own iterator.

The Concurrent of the ConcurrentHashMap with he iterator refer to cases which you are trying to put or remove a value from the map while iterating it - than it will be thread-safe. Though there is no guarantee that the other thread will see the changes unless it is obtaining a new iterator from the map.

I hope the information was usefull !

Upvotes: 2

Related Questions