Thread unsafe HashMap

Encountered a problem that while using a copy constructor of  java.util.HashMap I got this error

Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:394)
at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:413)
at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:412)
at java.util.HashMap.putAllForCreate(HashMap.java:558)
at java.util.HashMap.<init>(HashMap.java:298)
at ...

My code that caused this exception was a one liner
 Map<String,String> cp = new HashMap<String,String>(m);
Culprit here is the class variable m. It had so happened that while I was trying to create a copy instance of this class variable some other thread had changed it.
Here's a simple runnable code to reproduce this issue

import java.util.*;

public class ThreadUnsafeHashMap {
 public static void main(String[] args) {
 Thread manipulate = null;
 try {
 final Map<String, String> m = Collections.synchronizedMap(new LinkedHashMap<String, String>() {
 protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
 if (size() > 1000) {
 clear();
 }
 return false;

 }
 });

 manipulate = new MapManipulate(m);

 manipulate.start();

 while (true) {
 m.put(UUID.randomUUID().toString(), UUID.randomUUID().toString());
 }
 } finally {
 if (manipulate != null)
 manipulate.interrupt();
 }
 }

 private static class MapManipulate extends Thread {
 final Map m;

 public MapManipulate(Map m) {
 this.m = m;
 }

 @Override
 public synchronized void run() {
 while (true) {
 Map<String, String> cp= new HashMap<String, String>(m);//thread unsafe
 System.out.println(cp);
 try {
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }
 }
 }
}
And how to correct it?

@Override
 public synchronized void run() {
   while (true) {
     Map<String,String> cp
synchronised(m){
   cp = new HashMap<String,String>(m);//thread safe
}
     System.out.println(cp);
     try {
       Thread.sleep(1000);
     } catch (InterruptedException e) {
         e.printStackTrace();
     }
  }
 }
 }
}

Advertisements