【问题标题】:Synchronized Map or synchronized methods同步映射或同步方法
【发布时间】:2011-12-13 22:05:43
【问题描述】:

我有以下用于带同步方法的路由器表的类:

public class RouterTable {

    private String tableForRouter;
    private Map<String,RouterTableEntry> table;

    public RouterTable(String router){

        tableForRouter = router;
        table = new HashMap<String,RouterTableEntry>();
    }

    public String owner(){

        return tableForRouter;
    }

    public synchronized void add(String network, String ipAddress, int distance){

        table.put(network, new RouterTableEntry(ipAddress, distance));
    }

    public synchronized boolean exists(String network){

        return table.containsKey(network);
    }
}

多个线程将读取和写入 HashMap。我想知道是否最好删除方法上的同步并只使用 Collections.synchronizedMap(new HashMap

【问题讨论】:

标签: java dictionary collections thread-safety synchronized


【解决方案1】:

我建议使用ConcurrentHashmap。这是 Java 更高版本中引入的一种较新的数据结构。它提供线程安全并允许并发操作,而不是同步映射,它一次只执行一个操作。

如果地图是唯一需要线程安全的地方,那么只使用 ConcurrentHashmap 就可以了。但是,如果您有涉及更多状态变量的原子操作,我建议您使用同步代码块而不是同步函数

【讨论】:

    【解决方案2】:

    在没有对发生前关系和时间点正确性的严格要求的情况下,在现代 Java 中明智的做法通常是使用 ConcurrentMap

    否则,是的,与手动同步所有内容相比,使用 Collections#synchronizedMap 更安全且性能可能更高(因为您不会包含任何不需要同步的第三代代码)。

    【讨论】:

      【解决方案3】:

      最好的方法是使用 java.util.concurrent.ConcurrentHashMap,它从头开始设计用于并发访问(读取和写入)。

      像您一样使用同步是有效的,但显示出高争用,因此不是最佳性能。通过 Collections.synchronizedMap() 获得的集合会做同样的事情(它只用同步方法包装标准集合)。

      ConcurrentHashMap 相反,使用各种技术来保证线程安全并提供良好的并发性;例如,它(默认情况下)有 16 个区域,每个区域由不同的锁保护,因此最多 16 个线程可以同时使用它。

      【讨论】:

        【解决方案4】:

        同步地图会阻止您班级的用户进行有意义的同步。

        一旦进入if语句,他们将无法知道exists的结果是否仍然有效,并且需要进行外部同步。

        使用您展示的同步方法,它们可以锁定您的类,直到它们完成一个方法调用块。

        另一种选择是不进行同步,让用户自己处理,为了安全起见,他们无论如何都需要这样做。

        添加您自己的同步是 HashTable 的问题所在。

        【讨论】:

          【解决方案5】:

          当前的通用风格倾向于使用同步集合而不是访问它们的方法上的显式同步限定。但是,这不是一成不变的,您的决定应该取决于您使用此代码的方式/将来会使用此代码。

          需要考虑的要点:

          (a) 如果您的地图将被RouterTable 之外的代码使用,那么您需要使用SynchronizedMap

          (b) OTOH,如果您要向RouterTable 添加一些附加字段,并且它们的值需要与地图中的值一致(换句话说:您希望更改地图和附加场发生在一个原子量子中),那么您需要使用synchrnoized 方法。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-04-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多