Является 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
[email protected]
Have lock: 2
foo=null
New foo time! 2
[email protected]
Вторая нить не видит сразу! Зачем? На моей производственной системе больше потоков, и я видел только один поток, первый из которых сразу следует за потоком 1, имеет проблему.
Я даже попытался уменьшить уровень concurrency на ConcurrentHashMap до 1, но это не имеет значения. Например:.
static ConcurrentHashMap map = new ConcurrentHashMap(32, 1);
Где я ошибаюсь? Мое ожидание? Или есть какая-то ошибка в моем коде (реальное программное обеспечение, а не выше), которое вызывает это? Я много раз перебирал его и на 99% уверен, что правильно обрабатываю блокировку. Я даже не могу понять ошибку в ConcurrentHashMap
или JVM. Пожалуйста, спаси меня от себя.
Особенности Gorey, которые могут иметь значение:
- четырехъядерный 64-разрядный Xeon (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)
)