ConcurrentHashMap.get()是否保证通过不同的线程看到以前的ConcurrentHashMap.put()? [英] Is ConcurrentHashMap.get() guaranteed to see a previous ConcurrentHashMap.put() by different thread?

查看:133
本文介绍了ConcurrentHashMap.get()是否保证通过不同的线程看到以前的ConcurrentHashMap.put()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ConcurrentHashMap.get() 保证查看以前的 ConcurrentHashMap.put() 由不同的主题?我的期望是,并且阅读JavaDocs似乎表明了这一点,但我99%确信现实是不同的。在我的生产服务器上,下面的似乎正在发生。 (我已经记录了它。)

Is ConcurrentHashMap.get() guaranteed to see a previous ConcurrentHashMap.put() by different thread? My expectation is that is is, and reading the JavaDocs seems to indicate so, but I am 99% convinced that reality is different. On my production server the below seems to be happening. (I've caught it with logging.)

伪代码示例:

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");
} 

似乎正在发生的事情是:

What seems to be happening is this:

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

所以,我的输出如下所示:

So, my output looks like this:

Have lock: 1    
foo=null
New foo time! 1
foo=foo@cafebabe420
Have lock: 2    
foo=null
New foo time! 2
foo=foo@boof00boo    

第二个线程没有立即看到看跌期权!为什么?在我的生产系统上,有更多的线程,我只看到一个线程,第一个紧跟在线程1之后,有一个问题。

The second thread does not immediately see the put! Why? On my production system, there are more threads and I've only seen one thread, the first one that immediately follows thread 1, have a problem.

我甚至尝试将ConcurrentHashMap上的并发级别缩减到1,而不是它应该重要。例如:

I've even tried shrinking the concurrency level on ConcurrentHashMap to 1, not that it should matter. E.g.:

static ConcurrentHashMap map = new ConcurrentHashMap(32, 1);

我哪里错了?我的期望?或者我的代码(真正的软件,而不是上面的代码)中有一些错误导致了这个问题吗?我已经反复检查过,99%肯定我正确处理锁定。我甚至无法理解 ConcurrentHashMap 或JVM中的错误。 请救我自己。

Where am I going wrong? My expectation? Or is there some bug in my code (the real software, not the above) that is causing this? I've gone over it repeatedly and am 99% sure I'm handling the locking correctly. I cannot even fathom a bug in ConcurrentHashMap or the JVM. Please save me from myself.

可能相关的Gorey细节:

Gorey specifics that might be relevant:


  • 四核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位服务器VM(版本10.0-b23,混合模式)

  • quad-core 64-bit 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))

推荐答案

这里有一些好的答案,但据我所知,没有人提供过对问题的规范回答:ConcurrentHashMap.get()保证通过不同的线程看到以前的ConcurrentHashMap.put()。那些说是的人没有提供消息来源。

Some good answers here, but as far as I can tell no-one has actually provided a canonical answer to the question asked: "Is ConcurrentHashMap.get() guaranteed to see a previous ConcurrentHashMap.put() by different thread". Those that have said yes haven't provided a source.

所以:是的,保证。 来源(请参阅本节'内存一致性属性':

So: yes, it is guaranteed. Source (see the section 'Memory Consistency Properties'):


在将对象放入任何并发集合之前的线程中的操作发生在访问之后的操作之前或从另一个帖子中的集合中删除该元素。

Actions in a thread prior to placing an object into any concurrent collection happen-before actions subsequent to the access or removal of that element from the collection in another thread.

这篇关于ConcurrentHashMap.get()是否保证通过不同的线程看到以前的ConcurrentHashMap.put()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆