> class MyThread extends Thread {
> String sa;
> class Test {
> private static String sa = new String("Not Done");
> I am not sure how to interpret this.
There are two objects named "sa". I'd interpret it as f'd up.
> thread has the lock on the object sa (in the Test object). I'm not
The main thread does. The thread created from the MyThread object will
wait forever. The two never interact.
> sure if it matters if its a String (immutable) object and that it is a
> static object being synchronised.
I don't think it does. (In the general case, not because this program
doesn't really synchronize anything.)
> If it is being synchronised in a different thread (main and t1), does
> it matter?
It doesn't matter in this instance because two different objects are
used to synchronize two different threads. The locks and the threads
never interact.
This is a pretty basic exercise in "do you understand how to declare
variables" and has little to do with locks or threads.
Now lets see if I get totally proven wrong by someone ;) ....
Lew - 19 Feb 2008 04:56 GMT
> There are two objects named "sa". ...
lielar wrote:
>> If it is being synchronised in a different thread (main and t1), does
>> it matter?
> It doesn't matter in this instance because two different objects are
> used to synchronize two different threads. The locks and the threads
> never interact.
...
> Now lets see if I get totally proven wrong by someone ;)
You're totally right, Mark Space.
To the OP: What Mark pointed out is that for synchronization to work, the
locks must be taken on the *same* object. Not the same variable.
The distinction between variables and objects is quite significant. Variables
are pointers to objects (or primitives - forget them for now). Variables have
compile-time type and scope; objects have run-time type and lifespan.
Variables cannot hold locks. They have no locks. They point to objects that
have locks. (Technically, they have monitors, but that's not important here.)
The static variable
private static String sa = new String("Not Done");
is visible to the Test class only. It points initially to a new String with
the value "Not Done". The pointer to that String is passed to the MyThread
instance. The MyThread instance variable is never changed to point to a
different String thereafter.
Side note: The fact that the Test 'sa' variable is a static variable is
meaningless; it really should have been a constant (not a 'new String(...)')
or a local variable.
The statement
sa = new String("Done");
points the Test static variable 'sa' to a different object, in one thread.
That change cannot be seen in the other thread, because, a), it is never
passed to the MyThread instance, and, b), there isn't any synchronization on
involved in communicating the change to the instance.
Then the call to
sa.notify();
sends a 'wakeup' to all threads waiting on the lock for the new String with
value "Done". There aren't any.
You might also want to review the limitations of the notify() method for more
complex scenarios.
Now back to the idea of primitives. Synchronizing access to a primitive
instance variable works a little differently from object variables. Some
primitive operations are atomic, not that that excuses one from communicating
those operations synchronously.
<http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html>

Signature
Lew
lielar - 19 Feb 2008 10:03 GMT
Thanks for the reply.
The answer to question (which was what would be the output of the
following program?) is a runtime exception.
Now, correct me if I'm wrong, the reason is that notify is called on a
new String object as oppose to calling notify on an reference of an
object passed to a different thread (MyThread) which owns the object.
Meaning that the main thread is calling notify and MyThread is calling
wait?
> > There are two objects named "sa". ...
> lielar wrote:
[quoted text clipped - 53 lines]
> --
> Lew
Matt Humphrey - 19 Feb 2008 13:37 GMT
> Thanks for the reply.
>
[quoted text clipped - 6 lines]
> Meaning that the main thread is calling notify and MyThread is calling
> wait?
The runtime exception (IllegalMonitorState) occurs because Main does not
hold the lock (monitor) on the same string that is being used for notify.
You must be holding the lock when you call wait or notify. But even if you
were, the synchronization would still fail because the notify is occuring on
a different object from the wait (as Mark and Lew have pointed out).
Matt Humphrey http://www.iviz.com/