Java synchronized block vs. Collections.synchronizedMap

后端 未结 7 1920
天涯浪人
天涯浪人 2020-11-28 03:35

Is the following code set up to correctly synchronize the calls on synchronizedMap?

public class MyClass {
  private static Map

        
7条回答
  •  刺人心
    刺人心 (楼主)
    2020-11-28 04:00

    Yes, you are synchronizing correctly. I will explain this in more detail. You must synchronize two or more method calls on the synchronizedMap object only in a case you have to rely on results of previous method call(s) in the subsequent method call in the sequence of method calls on the synchronizedMap object. Let’s take a look at this code:

    synchronized (synchronizedMap) {
        if (synchronizedMap.containsKey(key)) {
            synchronizedMap.get(key).add(value);
        }
        else {
            List valuesList = new ArrayList();
            valuesList.add(value);
            synchronizedMap.put(key, valuesList);
        }
    }
    

    In this code

    synchronizedMap.get(key).add(value);
    

    and

    synchronizedMap.put(key, valuesList);
    

    method calls are relied on the result of the previous

    synchronizedMap.containsKey(key)
    

    method call.

    If the sequence of method calls were not synchronized the result might be wrong. For example thread 1 is executing the method addToMap() and thread 2 is executing the method doWork() The sequence of method calls on the synchronizedMap object might be as follows: Thread 1 has executed the method

    synchronizedMap.containsKey(key)
    

    and the result is "true". After that operating system has switched execution control to thread 2 and it has executed

    synchronizedMap.remove(key)
    

    After that execution control has been switched back to the thread 1 and it has executed for example

    synchronizedMap.get(key).add(value);
    

    believing the synchronizedMap object contains the key and NullPointerException will be thrown because synchronizedMap.get(key) will return null. If the sequence of method calls on the synchronizedMap object is not dependent on the results of each other then you don't need to synchronize the sequence. For example you don't need to synchronize this sequence:

    synchronizedMap.put(key1, valuesList1);
    synchronizedMap.put(key2, valuesList2);
    

    Here

    synchronizedMap.put(key2, valuesList2);
    

    method call does not rely on the results of the previous

    synchronizedMap.put(key1, valuesList1);
    

    method call (it does not care if some thread has interfered in between the two method calls and for example has removed the key1).

提交回复
热议问题