到目前为止,我使用了双重检查锁定,如下所示:
class Example {
static Object o;
volatile static boolean setupDone;
private Example() { /* private constructor */ }
getInstance() {
if(!setupDone) {
synchronized(Example.class) {
if(/*still*/ !setupDone) {
o = new String("typically a more complicated operation");
setupDone = true;
}
}
}
return o;
}
}// end of class
现在,因为我们有一组共享这个类的线程,所以我们将boolean
a更改ConcurrentHashMap
为如下:
class Example {
static ConcurrentHashMap<String, Object> o = new ConcurrentHashMap<String, Object>();
static volatile ConcurrentHashMap<String, Boolean> setupsDone = new ConcurrentHashMap<String, Boolean>();
private Example() { /* private constructor */ }
getInstance(String groupId) {
if (!setupsDone.containsKey(groupId)) {
setupsDone.put(groupId, false);
}
if(!setupsDone.get(groupId)) {
synchronized(Example.class) {
if(/*still*/ !setupsDone.get(groupId)) {
o.put(groupId, new String("typically a more complicated operation"));
setupsDone.put(groupId, true); // will this still maintain happens-before?
}
}
}
return o.get(groupId);
}
}// end of class
我现在的问题是:如果我将标准声明Object
为volatile
,我只会在读取或写入其引用时建立起之前的关系。因此,在该对象中编写一个元素(如果它是一个标准HashMap
,则对其执行put()
操作)将不会建立这种关系。那是对的吗?(阅读一个元素怎么样;那不需要阅读参考资料并因此建立关系吗?)
现在,使用 volatile ConcurrentHashMap,将向其写入元素会建立起之前的关系,即上述方法仍然有效吗?
更新:这个问题的原因以及为什么双重检查锁定很重要:
我们实际设置的(而不是对象)是 a MultiThreadedHttpConnectionManager
,我们将一些设置传递给它,然后我们将其传递给HttpClient
我们设置的 a ,太,我们回来了。我们有多达 10 个组,每组最多 100 个线程,并且我们使用双重检查锁定,因为我们不想在每个需要获取组的时候阻塞它们HttpClient
,因为整个设置将用于帮助提高性能测试。由于笨拙的设计和奇怪的平台,我们不能只从外部传入对象,所以我们希望以某种方式使这个设置工作。(我意识到这个问题的原因有点具体,但我希望这个问题本身足够有趣:有没有办法得到那个ConcurrentHashMap
使用“易变行为”,即volatile boolean
在put()
对ConcurrentHashMap
? ;)