Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When Should I synchronize the methods of my class?

Tags:

java

I was thinking about creating a class (like String, StringBuffer etc). This can be used in single-threaded as well as in multi-threaded environments. I do not know which kind of environment a developer might be using it. Anticipating the worst-case, I can synchronize.

But, 1. Synchronization takes a performance hit. 2. Without synchronization, it is not thread-safe.

So, I have two options.

  1. Leave the class unsynchronized - but the developer using this class needs to synchronize it whenever appropriate.
  2. Have all synchronized methods - and take a performance hit.

I have seen that many (if not all. for eg, ArrayList over Vector) classes in Java have evolved to take the first approach. What are some of the things I need to consider before deciding on these two options for my class?

Or to put it in a different way, should I use "public synchronized void bar()" over "public void bar()" only when I know for sure that bar can be used in a multi-threaded environment and should not be run at the same time?

EDIT So, clearly I have mis-used the word "utility class" in the heading. Thanks, Jon Skeet, for pointing it out. I have removed the world "utility" from the heading.

To give an example, I was thinking about a class like, say, Counter. Counter is just as an example. There are other ways to implement Counter. But this question is about synchronization. A Counter object keeps track of how many times something has been done. But it can possibly be used in single-threaded or multi-threaded environments. So, how should I handle the problem of synchronization in Counter.

like image 217
user1700184 Avatar asked Nov 01 '12 20:11

user1700184


People also ask

When should you synchronize a method?

We need to synchronize the shared resources to ensure that at a time only one thread is able to access the shared resource. If an Object is shared by multiple threads then there is need of synchronization in order to avoid the Object's state to be getting corrupted. Synchronization is needed when Object is mutable.

Do synchronized methods synchronize on the object or the class?

Synchronized static methods are synchronized on the class object of the class the synchronized static method belongs to. Since only one class object exists in the Java VM per class, only one thread can execute inside a static synchronized method in the same class.

Where synchronization is needed and why?

The need for synchronization originates when processes need to execute concurrently. The main purpose of synchronization is the sharing of resources without interference using mutual exclusion. The other purpose is the coordination of the process interactions in an operating system.

What does synchronizing a method do?

Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods.


1 Answers

Regarding your last question: you don't synchronize a method if it can be called from multiple threads. You synchronize a method if it uses some state that can be accessed from multiple threads.

So, even if your bar() method is called from only one thread, if it accesses an instance variable which is read and modified, through other methods, by multiple threads, then the bar() method must be synchronized (or at least, the block of code which accesses the shared variable). Synchronization is all about shared state.

EDIT:

Regarding your main problem: you could simply use the same strategy as the collection framework: make your Counter an interface, and provide a default, non-thread-safe implementation. Also provide a utility class (Counters) containing a method which returns a synchronized Counter proxy: Counters.synchronizedCounter(Counter counter);.

This way, you have the best of both worlds. Note that an important point of this design is that the synchronized counter is synchronized on itself. This makes it possible for the callers to add external synchronization in case two method calls on the counter must be done in an atomic way:

Counter synchronizedCounter = Counters.synchronizedCounter(c);
// call a and b atomically:
synchronized (synchronizedCounter) {
    synchronizedCounter.a();
    synchronizedCounter.b();
}
like image 106
JB Nizet Avatar answered Oct 27 '22 08:10

JB Nizet