【问题标题】:Synchronized Access of Static Map Object静态地图对象的同步访问
【发布时间】:2015-01-08 13:21:35
【问题描述】:

我在 Web 服务中使用了一个静态地图对象,它将在多线程环境中使用。

private static Map<String, String> map;

地图以键值对的形式保存数据库中的记录。因为,数据库很大,为每个请求执行读取操作将是一件昂贵的事情。我在服务启动期间读取了地图对象中的完整数据库,并且由于所有对象都应该共享相同的记录,因此我将其声明为静态。

static
{
      map = loadDatabase();
}

private Map<String,String> loadDatabase()
{   
    //database operations
    Map<String,String> sortedMap = new TreeMap<String,String>(new LengthBasedComparator());
    //put all records in a map in the length sorted manner
    return sortedmap            
}

我使用了TreeMap,因为我希望它根据键的长度进行排序。这是使用LenghBasedComparator 类完成的

如果它只是读取操作,它会工作得很好。

public String getStringMatch(String key)
{
   // additional processing
   map.get(key);
   // more processing
}

现在,更新内存数据库即地图的新要求出现了。

public String updateInMemoryDatabase(String key, String value)
{
    //....
    synchronized(map)
    {
       map.put(key,value);
    }
    return SUCCESS;
   //......
}

我已将put 操作放在地图上的synchronized 块中。

这是同步访问地图的正确方法吗?

或者,

  1. 使地图易变是否达到目的?
  2. 由于我需要排序方式的地图,我不能使用 ConcurrentHashMap。因为,它可能会改变排序。有什么使用方法吗?

请指点一下这方面。

谢谢

无所谓

【问题讨论】:

  • “数据库很大...我已经阅读了地图对象中的完整数据库”我知道“巨大”是一个主观术语,但如果它适合内存,你真的可以称之为巨大吗?
  • 同步 put() 是不够的。您还必须同步所有 get()。否则,一个线程可能会在另一个线程处于同步 put() 中间时执行不同步的 get(),并且第一个线程可能会看到 Map 处于无效状态,因此会得到错误的结果甚至使程序崩溃.
  • 不,volatile 无济于事。它不会阻止两个线程同时访问映射,在这种情况下,它可能根本不做任何事情,因为在第一次赋值之后没有线程写入 map 变量。注意:不存在 volatile object 这样的东西。如果你写volatile Map&lt;...&gt; map;,那是变量的一个属性。它不会改变变量所引用的 Map 对象的任何内容。
  • 在 TreeMap 中使用自定义比较器时要小心。如果您的比较器真的只比较长度,那么字符串的实际值无关紧要。在这一点上,你还不如拥有一个由 Integer(字符串长度)键入的映射。
  • @NishitJain 如果比较器说 2 个值相等(即长度相同),则映射会将 2 个键视为相等。如果这不是所需的行为,您需要通过提供另一个比较器来处理长度相同的情况。您可以恢复到 String 的自然比较作为辅助排序。在 Java 8 中:Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder())

标签: java multithreading web-services synchronization


【解决方案1】:

如果需要对键进行排序,则不能使用 ConcurrentHashMap,但可以使用 ConcurrentSkipListMap,这可能比尝试自己处理所有并发要好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    相关资源
    最近更新 更多