These questions explain what a monitor protects, how instance and class locks differ, and why unsynchronized access can defeat an otherwise careful locking policy.
Answer: Yes. Synchronization is applied to particular methods or blocks, not automatically to every operation on a class. An unsynchronized method can execute while another thread holds the receiver's monitor, unless it performs some other blocking or locking operation.
This is safe when the unsynchronized method does not access state that requires that monitor, or uses another correct mechanism. It is unsafe to assume that making only a setter synchronized protects an ordinary unsynchronized getter. Readers and writers must share a coherent policy for both atomicity and visibility.
Answer: An instance synchronized method locks its receiver. A static synchronized method locks the Class object representing its declaring class. A synchronized block locks the object produced by its expression, such as a private final lock field.
The identity of that object is decisive. Two different lock objects with equal contents are still different monitors. A null expression causes NullPointerException instead of acquiring a lock. Prefer a stable lock reference, and avoid exposing a private lock to unrelated callers who could interfere with the locking protocol.
Answer: It locks the Class object for the class that declares the method. For a method declared in Counter, that monitor is Counter.class. All calls using that same Class object coordinate, regardless of whether a caller happens to write the call through an instance expression.
Static methods should be called through the class name for clarity. Class identity also involves its defining class loader: classes with the same name loaded independently can have distinct Class objects. The lock is not a universal operating-system-wide lock based on a textual class name.
Answer: Mutual exclusion prevents different threads from simultaneously owning that monitor. Memory ordering makes writes before a monitor unlock visible to a thread that subsequently locks the same monitor. Together, these support compound operations over a protected invariant.
public class MonitorCounter {
private int value;
synchronized void increment() { value++; }
synchronized int value() { return value; }
public static void main(String[] args) throws InterruptedException {
MonitorCounter counter = new MonitorCounter();
Runnable task = () -> {
for (int i = 0; i < 1_000; i++) counter.increment();
};
Thread first = new Thread(task);
Thread second = new Thread(task);
first.start();
second.start();
first.join();
second.join();
System.out.println(counter.value());
}
}
The result is 2000. Both workers update the same counter under the same monitor, so an increment cannot lose another increment. The joins ensure printing occurs after both workers finish.
Answer: It is an expression yielding the Class object for the named type. It does not construct a Counter instance or read the contents of a .class file into an ordinary application object. Class literals also exist for primitive types, such as int.class, and array types.
The expression object.getClass() returns the object's runtime class, which may be a subclass of the type used to declare the reference. A named class literal identifies the stated type. This distinction matters when selecting a class monitor: locking a runtime subclass's Class object is not necessarily locking the declaring class of a static synchronized method.
Answer: No. An intrinsic monitor does not freeze an object or enforce field access permissions. Another thread can still execute code that reads or writes the fields without acquiring the monitor. Such access can produce races or stale observations.
A monitor works because participating code consistently follows the locking contract. Encapsulation helps keep that contract enforceable, but private fields alone are insufficient if the class's own methods access them inconsistently. Document which lock guards each mutable invariant, including any state reachable through collections or other referenced objects.
Answer: String is immutable: operations do not alter its character sequence. A method may return a new String or reuse an existing one where its contract permits. StringBuilder and StringBuffer are mutable character sequences; StringBuffer synchronizes its operations, whereas StringBuilder does not provide that synchronization.
For a builder confined to one thread, StringBuilder is usually appropriate. With shared StringBuffer use, a sequence such as checking the length and then updating is not automatically atomic merely because its individual calls are synchronized. Protect a required compound operation with a common lock, or avoid sharing the mutable builder.
Answer: A thread contending for an intrinsic monitor is BLOCKED. This includes reacquiring the monitor after Object.wait when another thread currently owns it. Once the monitor can be acquired and the thread is scheduled, it can continue.
Do not generalize BLOCKED to every operation that waits. Explicit lock implementations may park a thread in WAITING or TIMED_WAITING, and sleep uses TIMED_WAITING. Thread states describe the waiting mechanism, while stack traces and lock information help identify the actual cause during diagnosis.
Answer: Java does not specify a first-in-first-out winner or a particular priority-based selection. A contending thread becomes able to compete for the monitor, but availability does not guarantee immediate execution or acquisition by a particular waiter.
Do not build a turn-taking protocol from arrival order at synchronized methods. Express turns or dependencies with explicit state and condition checks. Some explicit locks offer a fairness option, but its contract still needs to be read carefully; fairness is not a general guarantee about CPU scheduling or application completion order.
Answer: Instance synchronization normally protects per-instance state by locking the receiver. Static synchronization locks the declaring Class object and can protect state shared across instances. Different receivers mean different instance monitors, while calls to a static synchronized method declared by the same class use one Class monitor.
The two mechanisms do not automatically exclude one another. If instance and static methods both access the same mutable shared state, they must adopt a common locking strategy or another correct concurrency mechanism. Choose by the ownership of the data, rather than mechanically matching static fields with static methods.
References: Synchronized methods, Monitor and memory-model rules, and StringBuffer.