问题描述
我有一段代码可以由需要执行I / O绑定操作的多个线程执行,以初始化存储在 ConcurrentMap $ c中的共享资源$ C>。我需要使这段代码线程安全,并避免不必要的调用来初始化共享资源。这是有缺陷的代码:
I have a piece of code that can be executed by multiple threads that needs to perform an I/O-bound operation in order to initialize a shared resource that is stored in a ConcurrentMap
. I need to make this code thread safe and avoid unnecessary calls to initialize the shared resource. Here's the buggy code:
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()
这都是昂贵的。为了确保共享资源只进行一次初始化并在资源初始化后使代码有效,我想做这样的事情:
With the above code, multiple threads may check the ConcurrentMap
and see that the resource isn't there, and all attempt to call getResource()
which is expensive. In order to ensure only a single initialization of the shared resource and to make the code efficient once the resource has been initialized, I want to do something like this:
String key = "somekey";
Resource resource;
if (!map.containsKey(key)) {
synchronized (map) {
if (!map.containsKey(key)) {
resource = getResource(key);
map.put(key, resource);
}
}
}
这是一个安全的版本吗?双重检查锁定?在我看来,由于在 ConcurrentMap
上调用了检查,它的行为就像一个声明为 volatile的共享资源
从而防止可能发生的任何部分初始化问题。
Is this a safe version of double checked locking? It seems to me that since the checks are called on ConcurrentMap
, it behaves like a shared resource that is declared to be volatile
and thus prevents any of the "partial initialization" problems that may happen.
推荐答案
是的,它是安全的。
如果 map.containsKey(key)
为true,则根据doc, map。 put(key,resource)
发生在它之前。因此 getResource(key)
在 resource = map.get(key)
之前发生,一切都安然无恙。
If map.containsKey(key)
is true, according to doc, map.put(key, resource)
happens before it. Therefore getResource(key)
happens before resource = map.get(key)
, everything is safe and sound.
这篇关于使用ConcurrentMap双重检查锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!