2
votes

1) Does a thread relinquish it's lock as soon as notify is invoked within that threads synchronized code block, or once the synchronized code block is exited?

For instance, it seems like without specifying thread priority, my Process class will execute from top to bottom. Produce will be called first, it will do stuff, then wait(); consume will run, and then it hits notify(), which will print "Done" or will there be a 5 second delay first, then "Done" will be printed?

2) Also, if I had a third synchronized method/thread, that does not wait or notify and just runs, can I predict the order in which my operations are executed a priori?

3) Finally, how does notify() know what thread to 'wake up'? Like, let's say I have multiple Processes each executing 2 threads simultaneously, and each Process A, B, and C evoke notify( ). Is each notify( ) local to each Process? In other words, if Process A calls notify( ), can that wake up a waiting thread in Process B? So far I've seen synchronized called on (this), which makes me think its referring to a particular object class, which in turn makes me think that all notify( )'s called in synchronized blocks are bound by whatever this in synchronized(this) is referring to, so there would be no cross-over.

public class Process {

public void produce( ) {
  synchronized(this) {
   // do stuff
    wait( );
     System.out.println("Done");
    }
}


public void consume( ) {
    synchronized(this) {
    // stuff
    notify(); 
    Thread.sleep(5000);
    }
}
}
2

2 Answers

4
votes

You can write a simple program to test this

public static void main(String[] args) throws Exception {
    final Process e = new Process();        
    Thread t = new Thread(new Runnable() {          
        @Override
        public void run() {
            try {
                Thread.sleep(10);
                e.consume();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    t.start();
    e.produce();
}

This program waits 5000 milliseconds and prints

Done

As for your questions

1) Does a thread relinquish it's lock as soon as notify is invoked within that threads synchronized code block, or once the synchronized code block is exited?

The javadoc of notify() states

If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation.**strong text A thread waits on an object's monitor by calling one of the wait methods.

The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object

So, no, the thread does not relinquish control of the lock when calling notify(). That will happen when code exits the synchronized block.

2) Also, if I had a third synchronized method/thread, that does not wait or notify and just runs, can I predict the order in which my operations are executed a priori?

You can estimate, but you can't be certain. Execution happens at the discretion of the Thread scheduler.

3) Finally, how does notify() know what thread to 'wake up'?

The call doesn't know. The Thread scheduler knows and chooses. You cannot control this.

The javadoc for wait() and notify() state

This method should only be called by a thread that is the owner of this object's monitor.

and

IllegalMonitorStateException - if the current thread is not the owner of this object's monitor.

So you can only call them on objects when you are inside a synchronized block that is synchronized on that object.

In your code example, the call

wait();

is implicitly doing

this.wait();
2
votes

Does a thread relinquish it's lock as soon as notify is invoked within that threads synchronized code block, or once the synchronized code block is exited?

When the 'synchronized' block exits. notify() doesn't itself affect the lock at all.

will there be a 5 second delay first, then "Done" will be printed?

Yes.

Also, if I had a third synchronized method/thread, that does not wait or notify and just runs, can I predict the order in which my operations are executed a priori?

You can't predict anything with threads. If you want a specific execution order you wouldn't use them.

Finally, how does notify() know what thread to 'wake up'?

It doesn't. It 'wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation.'

Like, let's say I have multiple Processes each executing 2 threads simultaneously, and each Process A, B, and C evoke notify( ). Is each notify( ) local to each Process?

notify() has nothing to do with your classes. It notifies an object and wakes up a thread.

In other words, if Process A calls notify( ), can that wake up a waiting thread in Process B?

Yes.

So far I've seen synchronized called on (this), which makes me think its referring to a particular object class

No. It refers to a particular object.

which in turn makes me think that all notify( )'s called in synchronized blocks are bound by whatever this in synchronized(this) is referring to, so there would be no cross-over.

Don't think it. You've over-thinking this. synchronized(x) synchronizes on the object x, and x.notify() notifies it. Period.