ConcurrentHashMap.get() 是否保证通过不同的线程看到以前的 ConcurrentHashMap.put()?
ConcurrentHashMap.get()
是否保证通过不同的线程看到以前的 ConcurrentHashMap.put()
?我的期望是,阅读JavaDocs似乎表明了这一点,但我99%相信现实是不同的。在我的生产服务器上,以下情况似乎正在发生。(我已经通过日志记录捕获了它。
伪代码示例:
static final ConcurrentHashMap map = new ConcurrentHashMap();
//sharedLock is key specific. One map, many keys. There is a 1:1
// relationship between key and Foo instance.
void doSomething(Semaphore sharedLock) {
boolean haveLock = sharedLock.tryAcquire(3000, MILLISECONDS);
if (haveLock) {
log("Have lock: " + threadId);
Foo foo = map.get("key");
log("foo=" + foo);
if (foo == null) {
log("New foo time! " + threadId);
foo = new Foo(); //foo is expensive to instance
map.put("key", foo);
} else
log("Found foo:" + threadId);
log("foo=" + foo);
sharedLock.release();
} else
log("No lock acquired");
}
似乎正在发生的事情是这样的:
Thread 1 Thread 2
- request lock - request lock
- have lock - blocked waiting for lock
- get from map, nothing there
- create new foo
- place new foo in map
- logs foo.toString()
- release lock
- exit method - have lock
- get from map, NOTHING THERE!!! (Why not?)
- create new foo
- place new foo in map
- logs foo.toString()
- release lock
- exit method
所以,我的输出看起来像这样:
Have lock: 1
foo=null
New foo time! 1
foo=foo@cafebabe420
Have lock: 2
foo=null
New foo time! 2
foo=foo@boof00boo
第二个线程不会立即看到 put!为什么?在我的生产系统上,有更多的线程,我只看到一个线程,紧跟在线程1之后的第一个线程,有问题。
我甚至尝试过将 ConcurrentHashMap 上的并发级别缩小到 1,但这并不重要。例如:
static ConcurrentHashMap map = new ConcurrentHashMap(32, 1);
我哪里出错了?我的期望?或者我的代码(真正的软件,而不是上面的软件)中有一些错误导致了这种情况?我已经反复检查了它,并且99%确定我是否正确处理了锁定。我甚至无法理解JVM中的错误。请把我从我自己身上救出来。ConcurrentHashMap
可能相关的戈里细节:
- 四核 64 位至强 (DL380 G5)
- RHEL4 ( ...
Linux mysvr 2.6.9-78.0.5.ELsmp #1 SMP
x86_64 GNU/Linux
) - Java 6 (,
build 1.6.0_07-b06
64-Bit Server VM (build 10.0-b23, mixed mode)
)