Is HashMap thread safe and why not?

Is HashMap thread safe and why not?

In concurrent programming, it is difficult to prove that a class is thread-safe, so we often try to prove that a class is thread-unsafe. The methods of proving are generally as follows:

1. The object cannot be released safely, and the construction process escapes;

2. The visibility of memory, the content cannot be released in time;

3. The operation is not atomic;

4. Read and write cannot be synchronized;

5. There is the possibility of deadlock;

We often say that HashMap is not thread safe, but how to prove it? Most of the online examples are analyzed from the source code, not from the running results. For this reason, I tried to construct a test case to prove that HashMap has a memory visibility problem. The specific thinking process is as follows:

1. Create multiple threads, all threads share a HashMap, and use the key value in the HashMap to determine whether the thread continues to run;

2. Store a key value in HashMap to indicate whether the thread continues to run;

3. Continuously update this key value and gradually stop all threads;

4. If there are unstopped threads, it means that HashMap is not thread-safe;

The following is the specific implementation:

public class HashMapTest {

    // Using ConcurrentHashMap works fine
    //final static ConcurrentHashMap<String, String> ch = new ConcurrentHashMap<>();
    final static HashMap<String, String> ch = new HashMap<>();

    // running thread
    public static class R implements Runnable {

        private String end;

        public R(String end) {
            super();
            this.end = end;
        }

        @Override
        public void run() {
            while(!this.end.equals(ch.get("end"))) {
                System.out.println(this.end);
            }
            System.out.println(this.end + ": is End!");
        }

    }

    public static void main(String[] args) {
        // start the thread
        for(int i = 0; i < 10; i++) {
            new Thread(new R(String.valueOf(i))).start();
        }
        new Thread(() -> {
            int j = 0;
            while(j < 10) {
                ch.put("end", String.valueOf(j));
                // Give other threads a chance to execute
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace ();
                }
                j ++;
            }
        }).start();
    }

}

Running the above example, in most cases, the thread cannot be terminated, but there is also a possibility that this thread has no chance to execute at all during the HashMap switching value, so we also need to analyze the printed results. Analysis, it is found that HashMap does have the problem of memory visibility.




Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324530056&siteId=291194637