Difficulty: Medium
Correct Answer: This code can throw an IllegalMonitorStateException at runtime because wait and notify are called without holding obj monitor.
Explanation:
Introduction / Context:
Java concurrency provides wait and notify methods on Object for thread coordination. However, these methods must be called only when the current thread holds the monitor of the object on which they are invoked. The provided method waitForSignal appears to use synchronization, but it synchronizes on Thread.currentThread() and then calls wait and notify on a different object. This pattern is a classic trick question used in interviews to test understanding of intrinsic locks and the correct use of wait and notify.
Given Data / Assumptions:
Concept / Approach:
The contract for Object.wait and Object.notify in Java requires that the calling thread owns the monitor of the object on which these methods are invoked. Ownership is acquired by entering a synchronized block or method that locks on that object. If a thread calls wait or notify without holding the correct monitor, the Java Virtual Machine throws IllegalMonitorStateException at runtime. In this code, the synchronized block acquires the monitor of Thread.currentThread(), but wait and notify are invoked on obj, whose monitor is never acquired. Therefore, both obj.wait and obj.notify violate the contract and can cause IllegalMonitorStateException to be thrown.
Step-by-Step Solution:
Step 1: Identify the lock object used in the synchronized statement: synchronized (Thread.currentThread()). This means the thread acquires the monitor of its own Thread object.
Step 2: Notice that inside the synchronized block, wait and notify are called on obj, which is a newly created Object that is not used in the synchronized expression.
Step 3: Recall the rule: before a thread calls obj.wait or obj.notify, it must hold the monitor of obj by synchronizing on obj.
Step 4: Because the code does not synchronize on obj, the current thread does not own obj monitor when obj.wait and obj.notify are executed.
Step 5: According to the Java specification, this misuse results in IllegalMonitorStateException at runtime, making option B the correct statement.
Verification / Alternative check:
If we correct the method to synchronise on obj instead of Thread.currentThread(), it might look like this: void waitForSignal() { Object obj = new Object(); synchronized (obj) { try { obj.wait(); } catch (InterruptedException e) { } obj.notify(); } } In this corrected version, the thread holds obj monitor when calling wait and notify, so IllegalMonitorStateException is not thrown due to monitor ownership. The original code does not follow this pattern, so it violates the required condition. Running the original code in a test program typically results in IllegalMonitorStateException being thrown when the JVM reaches obj.wait().
Why Other Options Are Wrong:
Option A mentions InterruptedException, which is a checked exception declared by Object.wait. However, in this code, the method does not declare or catch InterruptedException. The compiler would report an error unless the call to wait is inside a try catch block or the method declares throws InterruptedException. In the form shown, the primary runtime issue being tested is IllegalMonitorStateException, not interrupted status handling. Option C talks about TimeoutException after ten minutes, but this exception is not thrown by wait unless specific timed wait methods are used, and even then it is not named TimeoutException in core Object methods. Option D claims all statements are correct, which is not accurate given the issues with A and C. Option E claims the code is safe, which is clearly false. Only option B correctly identifies the IllegalMonitorStateException due to calling wait and notify on obj without holding its monitor.
Common Pitfalls:
A common mistake is to think that any synchronized block allows calling wait and notify on any object, but the lock object matters. Another pitfall is forgetting to handle InterruptedException when using wait correctly. Developers should always ensure that wait and notify are called inside synchronized blocks that lock on the same object, and they should handle interruption properly. In interviews, explaining the monitor ownership rule and identifying IllegalMonitorStateException in this code shows solid understanding of Java concurrency fundamentals.
Final Answer:
This code can throw an IllegalMonitorStateException at runtime because wait and notify are called on obj without holding obj monitor.
Discussion & Comments