I have always thought that synchronizing the run method in a java class which implements Runnable is redundant. I am trying to figure out why people do this:
public class ThreadedClass implements Runnable{ //other stuff public synchronized void run(){ while(true) //do some stuff in a thread } } }
It seems redundant and unnecessary since they are obtaining the object's lock for another thread. Or rather, they are making explicit that only one thread has access to the run() method. But since its the run method, isn't it itself its own thread? Therefore, only it can access itself and it doesn't need a separate locking mechanism?
I found a suggestion online that by synchronizing the run method you could potentially create a de-facto thread queue for instance by doing this:
public void createThreadQueue(){ ThreadedClass a = new ThreadedClass(); new Thread(a, "First one").start(); new Thread(a, "Second one, waiting on the first one").start(); new Thread(a, "Third one, waiting on the other two...").start(); }
I would never do that personally, but it lends to the question of why anyone would synchronize the run method. Any ideas why or why not one should synchronize the run method?
Synchronization is needed when Object is mutable. If shared Object is immutable or all the threads which share the same Object are only reading the Object's state not modifying then you don't need to synchronize it.
Synchronization in java is the capability to control the access of multiple threads to any shared resource. In the Multithreading concept, multiple threads try to access the shared resources at a time to produce inconsistent results. The synchronization is necessary for reliable communication between threads.
Synchronization is usually needed when you are sharing data between multiple invocations and there is a possibility that the data would be modified resulting in inconsistency. If the data is read-only then you dont need to synchronize. In the code snippet above, there is no data that is being shared.
If you synchronize a code block within that method then more than one thread can execute the method simultaneously, but only one thread can enter the synchronized block at a time. From this we can conclude that synchronizing on the smallest possible code block required is the most efficient way to do it.
Synchronizing the run(
) method of a Runnable
is completely pointless unless you want to share the Runnable
among multiple threads and you want to sequentialize the execution of those threads. Which is basically a contradiction in terms.
There is in theory another much more complicated scenario in which you might want to synchronize the run()
method, which again involves sharing the Runnable
among multiple threads but also makes use of wait()
and notify()
. I've never encountered it in 21+ years of Java.
There is 1 advantage to using synchronized void blah()
over void blah() { synchronized(this) {
and that is your resulting bytecode will be 1 byte shorter, since the synchronization will be part of the method signature instead of an operation by itself. This may influence the chance to inline the method by the JIT compiler. Other than that there is no difference.
The best option is to use an internal private final Object lock = new Object()
to prevent someone from potentially locking your monitor. It achieves the same result without the downside of the evil outside locking. You do have that extra byte, but it rarely makes a difference.
So I would say no, don't use the synchronized
keyword in the signature. Instead, use something like
public class ThreadedClass implements Runnable{ private final Object lock = new Object(); public void run(){ synchronized(lock) { while(true) //do some stuff in a thread } } } }
Edit in response to comment:
Consider what synchronization does: it prevents other threads from entering the same code block. So imagine you have a class like the one below. Let's say the current size is 10. Someone tries to perform an add and it forces a resize of the backing array. While they're in the middle of resizing the array, someone calls a makeExactSize(5)
on a different thread. Now all of a sudden you're trying to access data[6]
and it bombs out on you. Synchronization is supposed to prevent that from happening. In multithreaded programs you need simply NEED synchronization.
class Stack { int[] data = new int[10]; int pos = 0; void add(int inc) { if(pos == data.length) { int[] tmp = new int[pos*2]; for(int i = 0; i < pos; i++) tmp[i] = data[i]; data = tmp; } data[pos++] = inc; } int remove() { return data[pos--]; } void makeExactSize(int size) { int[] tmp = new int[size]; for(int i = 0; i < size; i++) tmp[i] = data[i]; data = tmp; } }
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