【发布时间】:2013-06-14 15:51:55
【问题描述】:
到目前为止,我使用的双重检查锁定如下:
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 更改为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,将向其写入一个元素建立发生前的关系,即上述方法仍然有效?
更新:这个问题的原因以及为什么双重检查锁定很重要:
我们实际设置的(而不是对象)是MultiThreadedHttpConnectionManager,我们将一些设置传递给它,然后我们将其传递给HttpClient,我们也设置它,然后返回。我们有多达 10 个组,每组最多 100 个线程,我们使用双重检查锁定,因为我们不想在需要获取组的 HttpClient 时阻止每个组,因为整个设置将用于帮助进行性能测试。由于笨拙的设计和奇怪的平台,我们不能只从外部传入对象,所以我们希望以某种方式使这个设置工作。 (我意识到问题的原因有点具体,但我希望问题本身足够有趣:有没有办法让ConcurrentHashMap 使用“易变行为”,即建立一个发生- 之前的关系,就像volatile boolean 所做的那样,在ConcurrentHashMap 上执行put() 时? ;)
【问题讨论】:
标签: java multithreading volatile concurrenthashmap happens-before