Caution: Don't synchronize a thread object's run() method because situations arise where multiple threads need to execute run(). Because those threads attempt to synchronize on the same object, only one thread at a time can execute run(). As a result, each thread must wait for the previous thread to terminate before it can access run().
From : http://www.javaworld.com/article/2074318/java-concurrency/java-101--understanding-java-threads--part-2--thread-synchronization.html?page=2
How can different threads execute, run() of same Thread object?
Some general advice about when it comes to synchronizing that seems relevant here: don't put synchronization in your threads or runnables, put it in the data structures that the threads are accessing. If you guard the data structure with locks then you are assured that no threads can access it in an unsafe way, because the data structure is enforcing safe access. If you leave synchronization up to the threads then someone can write a new thread that doesn't do the appropriate locking and possibly corrupt the data structures being accessed. Remember the point of synchronization is to protect data from unsafe concurrent modification.
(If you look at the JavaWorld article, listings 2 and 3 illustrate this; listing 3 is noticeably saner than listing 2 in that the FinTrans data is protecting its own integrity where listing 2 the threads are doing the synchronizing. The author argues for listing 3 as having better granularity for locking, and doesn't address the point about having data structures protect their own integrity. Maybe that's because he's whipping out toy examples and isn't taking any of them so seriously; after all, at the top of the page he's showing using a string as a lock, which is a pretty bad idea.)
Also the Java API documentation discourages you from locking on thread objects. The Java threading implementation locks on threads, for instance when joining a thread, so any manipulations you do may get tangled up with what the Java threading API does; for instance, if you try to lock on threads any notify calls you make may get consumed by other threads trying to join. Also you may see some strange things, for instance when a thread terminates it sends a notification to anything waiting on its monitor. If you make the run method of a Thread subclass synchronized then the running thread has to acquire its own lock. If another thread wants to join on it then (unless the subclassed Thread gives up the lock by waiting) that makes it impossible for any thread to join (since that involves waiting, which requires acquiring the lock on the Thread object), so instead of the joining thread briefly acquiring the lock and settling down to wait, the joining thread is likely to be hanging out in the waitset contending for the lock until the to-be-joined-on thread terminates.
Another point is it's better to implement your tasks as Runnables rather than as Thread objects. I cannot think of a situation where it would be preferable to implement the run method of a Thread object than to implement Runnable, unless I was trying to create a confusing situation on purpose, or was typing a fast-and-dirty demo. (I really wonder whether the reason for Thread implementing Runnable could be to make it more convenient for people to write fast-n-dirty demo code.) Making your task a Runnable makes it clear that you have some logic that isn't tied down to being run as a new thread but alternatively can be handed off to an executor which can be in charge of how that task is executed. (You can do this with a Thread object, but it's confusing.) So another reason not to be making a synchronized run method on Thread objects is because you shouldn't be subclassing Thread in order to override the run method (and in general it's usually preferable to use executors with Runnables over spinning up your own threads).
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