Collection.synchronizedMap vs. synchronization of individual methods in HashMap

What is the difference between Collections.synchronizedMap () and the wrapper around the HashMap with all synchronized methods. I see no difference, because Collections.synchronizedMap () internally supports the same lock for all methods.

Basically, what is the difference between the following code snippets

Class C { Object o; public void foo() { synchronized(o) { // thread safe code here } } } 

and

 Class C { Object o; public synchronized void foo() { } } 
+4
source share
6 answers

There is only one difference:

Collections.synchronizedMap may use a different monitor than itself.

Using synchronized methods is similar to using sychnchonized(this) blocks, which means that the shell will be a monitor and can be locked outside the shell.

If you do not want an external application to block your monitor, you need to hide it.

On the other hand, if you want to call several methods in streaming safe mode, this is the easiest way to lock the entire collection (but it is not very scalable, really).

Ps: for reuse, it is better to delegate method calls to the backup map than to override the class, because later you can switch to another map implementation without changing your wrapper.

+3
source

Both approaches acquire an on-site monitor and therefore must do exactly the same. The main reason for the difference is architectural. Synchronized wrapper makes it easy to expand the basic flow-free options.

Having said that not to use, use ConcurrentHashMap. He uses blocking to use it much faster than any approach (since they are the same in terms of overhead + competition). Interleave interlocking allows segments of the substrate array to be locked independently of each other. This means that it is less likely that two threads will require the same lock.

+2
source

Do not reinvent the wheel or use what the API provides.

+1
source

You should always decorate, and not combine all and all objects in one large class.

Always use a regular card and decorate it with collections, or use java.util.concurrent and use a real lock so that you can physically check and update the card. Tomorrow, you might want to change the Hashtable to a Treemap, and you will have problems if you are stuck in a hash table.

0
source

So why are you asking? :) Do you really think that if the class is placed in the java.util package, then some kind of magic happens and its java code works in some complicated way?

It really just wraps all methods with a synchronized block {} and nothing more.

UPD: the difference is that you are much less likely to make a mistake if you use a synchronized collection instead of doing all the synchronization materials yourself.

UPD 2: as you can see in the sources, they use the "mutex'-object" as a monitor. When you use a synchronized modifier in a method signature (i.e. synchronized void doSmth() ), the current instance of your object (i.e. this ) is used as a monitor. The two blocks of code below are the same:

1.

 synchronized public void doSmth () { someLogic (); moreLogic (); } synchronized public static void doSmthStatic () { someStaticLogic (); moreStaticLogic (); } 

2.

 public void doSmth () { synchronized (this) { someLogic (); moreLogic (); } } public static void doSmthStatic () { synchronized (ClassName.class) { someStaticLogic (); moreStaticLogic (); } } 
0
source

If thread safety exists, use concurrency packet data structures. Using a wrapper class will reduce all calls to the map in a sequential queue.

a) Threads awaiting operations at completely different points on the Card will wait for the same lock. Based on the number of threads, this can affect application performance.

b) Consider composite operations on the map. Using a single lock wrapper will not help. For instance. β€œSee if you are present, and then add aβ€œ view of operations. ”Stream synchronization will again become a problem.

0
source

Source: https://habr.com/ru/post/1300959/


All Articles