別のスレッドで前を見ることが保証されていますか?私の期待はそうです、そしてJavaDocsを読むことはそう示しているようです、しかし私は99%が現実が違うと確信しています。私の本番サーバーでは、以下のことが起こっているようです。(私はロギングでそれを捕らえました。)ConcurrentHashMap.get()
ConcurrentHashMap.put()
擬似コードの例:
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
2番目のスレッドはすぐにプットを見ません!なんで?私の本番システムでは、より多くのスレッドがあり、スレッド1の直後に続く最初のスレッドである1つのスレッドだけに問題があります。
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)
)