简体   繁体   English

同步映射或同步方法

[英]Synchronized Map or synchronized methods

I have the following class for a Router's table with synchronised methods: 对于具有同步方法的路由器表,我具有以下类:

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

Multiple threads will read and write to the HashMap. 多个线程将读写HashMap。 I was wondering if it would be best to remove the synchronized on the methods and just use Collections.synchronizedMap(new HashMap<String,RouterTableEntry())` what is the most sensible way in Java to do this? 我想知道是否最好删除方法上的sync并仅使用Collections.synchronizedMap(new HashMap <String,RouterTableEntry())`Java中最明智的方法是这样做?

I would suggest using a ConcurrentHashmap . 我建议使用ConcurrentHashmap This is a newer data structure introduced in later version of Java. 这是Java的更高版本中引入的更新的数据结构。 It provides thread safety and allows concurrent operations, as opposed to a synchronized map, which will do one operation at a time. 与同步映射相反,它提供线程安全性并允许并发操作,而同步映射将一次执行一个操作。

If the map is the only place where thread safety is required, then just using the ConcurrentHashmap is fine. 如果该映射是唯一需要线程安全的地方,则只需使用ConcurrentHashmap即可。 However, if you have atomic operations involving more state variables, I would suggest using synchronized code blocks instead of synchronized functions 但是,如果您有涉及更多状态变量的原子操作,我建议您使用同步代码块而不是同步函数

In the absence of strict requirements about happens-before relationships and point in time correctness, the sensible thing to do in modern java is usually just use a ConcurrentMap . 在没有对先发生关系和时间点正确性的严格要求的情况下,现代Java中要做的明智的事情通常只是使用ConcurrentMap

Otherwise, yes, using a Collections#synchronizedMap is both safer and likely more performant (because you won't enclose any tertiary code that doesn't need synchronization) than manually synchronizing everything yourself. 否则,可以,与您自己手动同步所有内容相比,使用Collections#synchronizedMap更安全,而且性能更高(因为您不会封装不需要同步的任何三次代码)。

The best is to use a java.util.concurrent.ConcurrentHashMap, which is designed from the ground up for concurrent access (read & write). 最好是使用java.util.concurrent.ConcurrentHashMap,它是从头开始设计用于并发访问(读和写)的。

Using synchronization like you do works, but shows high contention and therefore not optimal performance. 像您一样使用同步是可行的,但是显示出较高的竞争性,因此不是最佳性能。 A collection obtained through Collections.synchronizedMap() would do just the same (it only wraps a standart collection with synchronized methods). 通过Collections.synchronizedMap()获得的集合将执行相同的操作(它仅包装具有同步方法的标准集合)。

ConcurrentHashMap, on the contrary, used various techniques to be thread-safe and provide good concurrency ; 相反,ConcurrentHashMap使用了各种技术来保证线程安全并提供良好的并发性。 for example, it has (by default) 16 regions, each guarded by a distinct lock, so that up to 16 threads can use it concurrently. 例如,它具有(默认情况下)16个区域,每个区域都有一个单独的锁保护,因此最多16个线程可以同时使用它。

Synchronizing the map will prevent users of your class from doing meaningful synchronization. 同步地图将阻止您班级的用户进行有意义的同步。

They will have no way of knowing if the result from exists is still valid, once they get into there if statement, and will need to do external synchronization. 一旦进入if语句,他们将无法知道结果是否仍然有效,并且需要进行外部同步。

With the synchronized methods as you show, they could lock on your class until they are done with a block of method calls. 使用您显示的同步方法,它们可以锁定您的类,直到用一个方法调用块完成它们为止。

The other option is to do no synchronization and let the user handle that, which they need to do anyway to be safe. 另一种选择是不进行同步,而是让用户处理该同步,以确保安全,他们仍然需要这样做。

Adding your own synchronization is what was wrong with HashTable. 添加自己的同步是HashTable的问题所在。

The current common style tends to prefer Synchronized collections over explicit synchronized qualification on the methods that access them. 当前的通用样式在访问它们的方法上倾向于优先使用同步集合,而不是显式同步限定。 However, this is not set in stone, and your decision should depend on the way you use this code/will use this code in the future. 但是,这不是一成不变的,您的决定应取决于您使用此代码的方式/将来将使用此代码。

Points to consider: 要考虑的要点:

(a) If your map is going to be used by code that is outside of the RouterTable then you need to use a SynchronizedMap . (a)如果您的映射将由RouterTable外部的代码使用,则您需要使用SynchronizedMap

(b) OTOH, if you are going to add some additional fields to RouterTable , and their values need to be consistent with the values in the map (in other words: you want changes to the map and to the additional fields to happen in one atomic quantum), then you need to use synchrnoized method. (b)OTOH,如果您要向RouterTable添加一些其他字段,并且它们的值必须与地图中的值一致(换句话说:您希望对地图和其他字段的更改要在一个中发生原子量子),那么您需要使用synchrnoized方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM