Java – double check locking using regular HashMap

Back to concurrency So far, it's clear that for double check locking, variables need to be declared volatile However, if double check locking is used, as shown below

class Test<A,B> {

    private final Map<A,B> map = new HashMap<>();

    public B fetch(A key,Function<A,B> loader) {
        B value = map.get(key);
        if (value == null) {
            synchronized (this) {
                value = map.get(key);
                if (value == null) {
                    value = loader.apply(key);
                    map.put(key,value);
                }
            }
        }
        return value;
    }

}

Why does it have to be a concurrent HashMap instead of a regular HashMap? All mapping modifications are done in synchronized blocks, and the code does not use iterators. Therefore, technically, there should be no "concurrent modification" problem

Please do not recommend putifabsent / computeifabsent, because I am asking for concepts instead of API:) unless using this API is helpful for HashMap and concurrenthashmap topics

Update 2016-12-30

Holger's comment answered this question: "hashmap.get does not modify the structure, but your put call is indeed so. Because you call get outside the synchronized block, it can see that the incomplete state actions of put occur at the same time." thank you!

Solution

The question is so confused that it is difficult to answer

If you call this code from only one thread, you are too complex; You don't need any synchronization But obviously this is not your intention

Therefore, multiple threads will call the fetch method, which delegates to HashMap. Net without any synchronization get(). HashMap is not thread safe BAM, the end of the story It doesn't matter if you're trying to simulate double check locking; The reality is that calling get () and put () on the map will manipulate the internal variable data structure of HashMap without consistent synchronization on all code paths, and you are dead because you can call these from multiple threads at the same time

In addition, you may think HashMap. Get () is a read - only operation, but this is also wrong What if HashMap is actually a LinkedHashMap (it is a subclass of HashMap) BlinkHashMap. Get () will update the access order, which involves writing the internal data structure - there is no synchronization here But even if get () is not written, your code will still be broken.)

Rule of thumb: when you think you have a clever technique to avoid synchronization, you are almost certainly wrong

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>