Background of the question:
Since the emergence of Java, developers have faced the issue of concurrent access to shared resources. To address this, high-level synchronization primitives were introduced, the main one being the synchronized key modifier.
Problem:
Without synchronization in multithreaded applications, shared resources can be corrupted: a data race occurs, and the object's state becomes unpredictable.
Solution:
synchronized allows organizing a monitor for a method or a block of code, providing access to only one thread at a time to the critical section. Thread synchronization can be implemented at the method or block level.
Example of locking an object:
public class Counter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; } }
Blocks can also be synchronized:
public void safeIncrement() { synchronized(this) { count++; } }
Key features:
What is the difference between a synchronized method and a synchronized block?
The synchronized method locks the entire method for the current object (this) or the class (if the method is static). The block allows synchronizing only the required piece of code and selecting any object for locking.
Can two different threads simultaneously enter two different synchronized methods of the same object?
No, if the methods are synchronized on the same monitor (this). If different monitors are used, then yes.
Does the synchronized modifier affect the visibility of variables between threads?
Yes, entering a synchronized block flushes the thread caches and updates variable values (happens-before relationship).
A developer synchronizes static methods of a class on an instance object, which does not guarantee correctness when used across different instances.
Pros:
Cons:
All methods using a shared resource are synchronized on a single monitor object, and the critical section's scope is minimal.
Pros:
Cons: