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.
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.
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.
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.
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.
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.
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With