Domanda

I have two blocks of code, one waits for the other to notify it.

synchronized(this) {
    wait();
}

and

while(condition) {
    //do stuff
    synchronized(this) {
        notify();
    }
}

Weirdly enough that didn't wait for the notify while this did:

synchronized(objectLock) {
    objectLock.wait();
}

and

while(condition) {
    //do stuff
    synchronized(objectLock) {
        objectLock.notify();
    }
}

I'm very curious about the difference of both sets, and why the first one worked while the other didn't. Note that the two blocks reside in two different threads on two different methods (if that helps).

I hope someone could explain why this is so. I edited my question so it would be more detailed.

È stato utile?

Soluzione

It didn't work because you synchronized on this which in two different threads pointed to two different Thread objects.

Synchronization with wait() and notify() would only work properly when you synchronize on the same object for locking like the objectLock that you used later on.

EDIT: If the two thread instances belonged to the same MyThread class then to achieve the effect that you thought you're code was having, you would have to acquire a lock on their class object itself:

synchronized(MyThread.class)

Altri suggerimenti

You can use any object you like. However, it is generally clearer to other programmers to see an explicit lock object.

My wild guess as to why this didn't work for you is you had a different this in scope. (ie, in an anonymous function/callback). You can be explicit about which this to use by appending the class name, eg, WonderClass.this - again a reason why this is not as clear. (edit: actually WhateverClass.this won't help you if this really is a different instance)

Also do read this: http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html - I generally find it easier to put all the thread-unsafe code into small synchronized methods (which do an implict lock on this)

When you say the two blocks reside in two different threads that makes me think they're not locking on the same object because this is not the same thing. When you name an explicit lock you're using the same thing to lock on.

By the way you should call wait in a loop, like this:

synchronized(someLock) {
   while (!someCondition) {
       wait();
   }
   // now the thread has the lock and it can do things 
   // knowing for sure that someCondition is true
}

Without this you will be vulnerable to spurious wakeups (not all notifications come from your application code) and the order in which wait and notify are called becomes problematic (if you have two threads and one notifies before the other waits then that notification never gets seen).

I'd advise using the Monitor pattern (http://en.wikipedia.org/wiki/Monitor_(synchronization)) anyway, that could save you from errors later on, especially as your use case gets more complex:

class Monitor
{
    /** Initialised to `false` by default in Java. */
    boolean condition;

    synchronized void waitForSomething()
    {
        while(!condition)
        {
            wait();
        }
    }

    synchronized void signal()
    {
        condition = true;

        notify();
    }
}

That way everything is nicely encapsulated and protected (I don't usually use private modifiers in examples, but you might want to enforce additional "privacy" in your code, specifically making the condition private.)

As you can observe, in my condition loop there is wait() call, as opposed to your example where you have notify() in the loop instead. In most use cases doing what you did with notify is a mistake, although I can't speak for your particular case as you didn't provide us with enough details. I am willing to bet yours is the typical one though, for which the Monitor pattern applies beautifully.

The usage scenario is along the following: thread that wants to wait for something calls waitForSomething and another thread may cause it to continue by invoking signal method which will set the condition flag.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top