【问题标题】:Using ConcurentHashMap and AtomicInteger as instance variables within a spring service class在 Spring 服务类中使用 ConcurentHashMap 和 AtomicInteger 作为实例变量
【发布时间】:2012-06-20 19:22:09
【问题描述】:

我正在尝试在注入控制器的单例 spring 服务中实现 ConcurentHashMap 的线程安全使用:

@Service
public MyService{

  final ConcurrentMap<String, AtomicInteger> myMap = new ConcurrentHashMap<String,   AtomicInteger>(10) {
        {/* initialize the ten key/values */
        }
    };

 public int add(String key) {
   return myMap.get(key).incrementAndGet();
 }

    // accessed via ajax loop (and controller), if value changes update display
  public int getCount(String key) {
    return myMap.get(key).get();
  }
}

有没有更好的方法可以让访问 hashmap 线程安全?我怎样才能使它适应在集群环境中工作?这是对my other question.的跟进

【问题讨论】:

  • 你看过Guava的ConcurrentHashMultiset,基本上就是这个东西吗?如果你不想要额外的导入,你至少可以看看源代码......
  • 只是为了确认我的理解.....“集群”是指多台服务器吗?
  • @J-16SDiZ 是的,我正在考虑在 tomcat/spring web 环境中,我对在 spring 服务类中获得线程安全的最佳方法更感兴趣
  • 如果你想跨多个服务器工作,你需要像memcached这样的服务。它有原子incr / decr 命令。
  • 以上代码是线程安全且正确的。让它在集群环境中工作确实需要一个集中式服务器、缓存或数据库。

标签: java multithreading spring concurrency


【解决方案1】:

我不打算为这个问题提供答案,尤其是。因为我没有集群情况下的专业知识;不过,我想指出我认为值得注意的地方。

@JB Nizet 在其中一个 cmets 中提到代码是线程安全的并且正确。我想根据Java API Reference添加但不一致

检索操作(包括get)一般不会阻塞,所以可能 与更新操作重叠(包括 put 和 remove)

这意味着当某些更新当前正在运行时,可能会有客户端获取此信息。而且,这是有道理的,因为您在代码中提到了“循环”。因此,如果这对您的情况很重要,那么一切都应该没问题。

但是,如果您需要更严格,我想也许使用ReentrantReadWriteLock 的实例可能是一个不错的选择。锁定使您的代码能够阻止所有读取请求,直到有可用信息的一致快照。您可能会使用getCount 方法上的锁来严格阻塞,直到add 方法释放所有等待代码中使用的地图的一致快照的锁。

我还猜测,当您将其迁移到集群解决方案时,同样的问题是有效的;如果在不同的集群节点之间需要一致性,那么应该注意它。

【讨论】:

  • OP 的答案中列出的getAtomicInteger不是 ConcurrentHashMap。因此,OP 在他的答案中列出的所有内容都是线程安全且一致的。
猜你喜欢
  • 1970-01-01
  • 2011-01-06
  • 1970-01-01
  • 2012-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-16
相关资源
最近更新 更多