Java synchronization by objects

I am trying to make sure that I understand the implications of synchronization associated with java. I have some simple classes:

public class ClassOne { private ClassTwo classTwo = new ClassTwo(); public synchronized void setClassTwo(int val1, int val2) { classTwo.setVal(val1); classTwo.setVal2(val2); } public static void main(String[] args) { ClassOne classOne = new ClassOne(); classOne.setClassTwo(10, 100); } } public class ClassTwo { private int val; private int val2; public synchronized void setVal(int val) { this.val = val; } public synchronized void setVal2(int val2) { this.val2 = val2; } } 

So, as you can see in the previous example, I sync to ClassOne.setClassTwo and ClassTwo.setVal and ClassTwo.setVal2. I am wondering if the performance will be the same if I remove the synchronization in ClassTwo.setVal and ClassTwo.setVal2, for example:

 public class ClassTwo { private int val; private int val2; public void setVal(int val) { this.val = val; } public void setVal2(int val2) { this.val2 = val2; } } 

They are functionally equivalent in this scenario (assuming that none of the other classes use these classes), but wondering how much overhead (if any) has a lot of synchronization.

+6
source share
3 answers

Will there be overhead? Yes.

Will there be a lot of overhead? It depends.
If there is only one thread, then the answer is "No", even in these ancient times , conflict-free synchronization was fast, presumably they have improved it since then.

So what happens if there are more than 1 thread? Well here is the problem: 2 versions you published are not functionally equivalent. What for? Because the subtopics you invoke are public methods of the open class. Therefore, they can be called outside of your setClassTwo and therefore do not have synchronization.

Another thing is that they are synchronized on different monitors. The second version is synchronized only on 1 monitor, and the original on two.

TL DR

Leave synchronized in the methods you need to synchronize, do not just expect the caller to synchronize (if it is not built into the class API). If the calling methods do the correct synchronization, there will be no competition, and the overhead will be very small, and if they do not do it in any way (for example, someone will call your method directly), then you will get competition and big overhead - but you still have thread safety.

+5
source

In the first case, you can create multiple threads and directly access setVal() in ClassTwo and not worry about memory inconsistencies ( setVal() synchronization on ClassTwo ). In the second case, you will have to be prepared for unexpected results if you start several threads and call setVal() directly. Also, if you are always sure that setVal() will only be called from setClassTwo() , then I suggest you synchronize the Class2 instance using a synchronized block and save setVal() and setVal2() as synchronized. The rule of thumb is to synchronize only what can be accessed.

+1
source

How you synchronize also depends on how you plan to use ClassTwo. If writing is rare and reading is frequent, readwritelock can give you better performance on a large scale. Reading is usually difficult only if the write is in progress, because read locks are shared by multiple read streams, while writing locks everything until the write is complete.

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReadWriteLock.html

Hope this helps.

+1
source

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


All Articles