OCJP Dumps Thread Synchronized Method

318 Views Asked by At

Hi I am working on SCJP dumps but now I got a problem. Here is the question:

void waitForSignal(){
   Object obj = new Object();
   synchronized(Thread.currentThread()){
       obj.wait();
       obj.notify();
   }
}

Which statement is true?

A. This code can throw an InterruptedException

B. This code can throw an illegalMonitorStateException

C. This code can throw a TimeoutException after ten minutes

D. Reversing the order of obj.wait() and obj.notify() might cause this method to complete normally

E. A call to notify() or notifyAll() from another thread might cause this method to complete normally

F. This code does NOT compile unless "obj.wait()" is replace with "((Thread) obj).wait()"

I found that in one dump file the answer is A, while in another dump the answer is B. Can anyone get the right answer and provide explanantion for me?

1

There are 1 best solutions below

0
Nathan Hughes On

Definitely B is correct here. See the API documentation for IllegalMonitorStateException:

Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.

The monitor acquired is the current thread (which the API documentation warns against doing, by the way). The methods wait and notify are called on obj, where they should have been called on the current thread object.

A. Object#wait can throw InterruptedException. Whether this happens is implementation-dependent, the language spec says:

Let thread t be the thread executing the wait method on object m, and let n be the number of lock actions by t on m that have not been matched by unlock actions. One of the following actions occurs:

  • If n is zero (i.e., thread t does not already possess the lock for target m), then an IllegalMonitorStateException is thrown.

  • If this is a timed wait and the nanosecs argument is not in the range of 0-999999 or the millisecs argument is negative, then an IllegalArgumentException is thrown.

  • If thread t is interrupted, then an InterruptedException is thrown and t's interruption status is set to false.

  • Otherwise, the following sequence occurs: (...)

so it's not strictly defined which of these cases will be checked first. In practice InterruptedException doesn't get thrown in the Oracle or IBM JDKs, IllegalMonitorStateException does.

But this code by itself won't cause an InterruptedException, something needs to call interrupt on the thread. The code I used to try this out was:

public class Test implements Runnable {

    public void run() {
        Object obj = new Object();
        Thread.currentThread().interrupt();
        try {
            synchronized(Thread.currentThread()) {
                obj.wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new Thread(new Test()).start();
    }
}

So A might be correct in theory. Certification test questions need to be reasonably clear-cut, that the spec is a little ambiguous about this point makes me think this is not a great test question.

C. "TimeoutException" is bogus. If a wait with a timeout passed in expires the method returns normally.

D. Reversing the order of the wait and notify calls doesn't matter, they both have the same requirement.

E. Nothing done by another thread can make this thread complete normally as it is written.

F. The method wait is on Object, not Thread, no cast is required.

Given that B is definitely true and it describes an important point that needs to be understood by Java programmers, while A is based on obscure quibbling about the spec, if you can pick only one answer I'd recommend B.