1

我将ConcurrentHashMap其存储在 servlet 上下文中,映射中的数据同时更改,我知道 servlet 上下文不是线程安全ConcurrentHashMap的,但是(用于编写)。在这种情况下我应该使用同步构造吗?

 synchronized (context) {
   ConcurrentHashMap messages =(ConcurrentHashMap)context.getAttribute("map");
   String mes  = messages.get("id");  // can be changed by another thread?
   messages.put("id",mes +"changed by thread 1");   
  }
4

3 回答 3

1

如果您在 ServletContext 初始化时存储 Map,那么您不需要同步获取它,因为在上下文关闭之前您不会删除它。

Map 是否处理并发并不重要。在后一种情况下,您需要在 Map 上进行同步,但由于您使用的是处理并发的,您甚至不需要这样做。

于 2012-08-02T13:37:08.813 回答
1

对不起,但我没有看到问题。在这个例子中,“消息”是一个局部变量,每个线程都有一个。你没有分享“信息”

当您从“上下文”中读取时,可能会出现唯一的问题,因此您只需要同步该读取

ConcurrentHashMap messages = null;
synchronized (context) {
    ConcurrentHashMap messages =(ConcurrentHashMap)context.getAttribute("map");
}
String mes  = messages.get("id");  // can be changed by another thread?
messages.put("id",mes +"changed by thread 1");   

但是,最好的办法是避免这种情况。您将如何避免在读取表单上下文中同步?很简单,您不能在上下文中编写或仅在初始化过程中这样做。

于 2012-08-02T16:22:28.857 回答
0

如果您担心在持有对 Map 的引用后对其进行更改,您可以做的是通过返回 Map 副本的方法包装代码。在这种情况下,您将从复制时保存地图的快照。

如果要完全同步更改,可以使用 Collections.syncrhonizedMap(...)

于 2012-08-02T13:54:19.117 回答