To avoid data corruption in multithreaded Java programs, shared data must be protected from concurrent modifications and accesses, as detailed in VOID CON00-J. Synchronize access to shared mutable variables. This can be done at the object level by using synchronized
blocks (coarse-grained locking), as a result locking out other threads from interfering. If synchronization is used judiciously, deadlocks do not usually crop up (See CON08-J. Do not invoke a superclass method or constructor when synchronizing on a superclass objectcall alien methods or constructors that synchronize on the same object as the calling class).
If however, one follows a fine-grained locking approach by using member locks, deadlocks can still arise unless it is ensured that each and every thread always requests locks in the same order.
...