简体   繁体   中英

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. 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?

I would suggest using a ConcurrentHashmap . This is a newer data structure introduced in later version of 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. 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 .

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.

The best is to use a java.util.concurrent.ConcurrentHashMap, which is designed from the ground up for concurrent access (read & write).

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).

ConcurrentHashMap, on the contrary, used various techniques to be thread-safe and provide good concurrency ; for example, it has (by default) 16 regions, each guarded by a distinct lock, so that up to 16 threads can use it concurrently.

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.

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.

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 .

(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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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