我有一段代码可以由多个线程执行,这些线程需要执行I / O绑定操作才能初始化存储在ConcurrentMap中的共享资源。我需要使此代码线程安全,并避免不必要的调用来初始化共享资源。这是越野车代码:

    private ConcurrentMap<String, Resource> map;

    // .....

    String key = "somekey";
    Resource resource;
    if (map.containsKey(key)) {
        resource = map.get(key);
    } else {
        resource = getResource(key); // I/O-bound, expensive operation
        map.put(key, resource);
    }


使用上面的代码,多个线程可以检查ConcurrentMap并查看资源是否不存在,并且所有尝试调用getResource()的操作都非常昂贵。为了确保仅对共享资源进行一次初始化并在初始化资源后使代码高效,我想执行以下操作:

    String key = "somekey";
    Resource resource;
    if (!map.containsKey(key)) {
        synchronized (map) {
            if (!map.containsKey(key)) {
                resource = getResource(key);
                map.put(key, resource);
            }
        }
    }


这是双重检查锁定的安全版本吗?在我看来,由于检查是在ConcurrentMap上调用的,因此它的行为就像是声明为volatile的共享资源,因此可以防止发生任何“部分初始化”问题。

最佳答案

是的,这很安全。

根据文档,如果map.containsKey(key)为true,则map.put(key, resource)在它之前发生。因此,getResource(key)发生在resource = map.get(key)之前,一切安然无sound。

关于java - 使用ConcurrentMap仔细检查了锁定,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/61514288/

10-15 09:42