Do you need to synchronize parallel collections?

Consider the following example: An application starts two threads. The Provider class contains the parallel collection and writes data to it. The consumer reads data from the collection.

Is the following code correct or do I need to add sync?

public class Application{
    public static void main(String...args) throws Exception{
        Provider p = new Provider();
        new Thread(p).start();
        new Thread(new Consumer(p)).start();

        // Make sure the example stops after 60 seconds
        Thread.sleep(1000*60);
        System.exit(0);
    }
}

/**The Provider (writes data to concurrent collection)*/
class Provider implements Runnable{

    private ConcurrentMap<Integer, String> map 
        = new ConcurrentHashMap<Integer, String>(20, 0.5f, 1);

    public void run(){
         Integer i = 1;
         while(true){
             try {
                 Thread.sleep(500);
             } catch (InterruptedException ignore) {
             }
             // Synchronization ?
             map.put(i, i.toString());
             i++;
         }
    }

    public ConcurrentMap<Integer, String> getMap(){
         // Synchronization ?
         return map;
    }

}

/**The Consumer (reads data from concurrent collection)*/
class Consumer implements Runnable{

    private Provider provider;

    public Consumer(Provider p){
        provider = p;
    }

    public void run(){
        while(true){
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException ignore) {
             }
            // Synchronization ?
            ConcurrentMap<Integer, String> m = provider.getMap();
            if(m!=null)
                for(String s: m.values())
                    System.out.print(s); 
            System.out.println();               
        }
    }

}

      

+3


source to share


2 answers


From the ConcurrentHashMap

documentation
:

For aggregate operations such as putAll

and clear

, concurrent retrieval may reflect the insertion or deletion of only some records. By analogy, Iterators, delimiters, and enumerations return items that reflect the state of the hash table at some point in time or after the creation of the iterator / enumeration. They don't throw it away ConcurrentModificationException

. However, iterators are only meant to be used one thread at a time. Keep in mind that the results of aggregate state methods, including size

, isEmpty

and containsValue

are usually only useful when the map is not undergoing concurrent updates in other threads. Otherwise, the results of these methods reflect transients that may be adequate for monitoring or evaluation purposes but not for program management.



So you don't need to sync as you won't get ConcurrentModificationException

. Regardless of whether you want your programming logic.

+2


source


Mutations in parallel collections are thread safe, but data consistency is not guaranteed.



An alternative Collections.synchronized[...]

idiom, when combined with explicit synchronization, will provide data security and thread safety (at the expense of performance).

+2


source







All Articles