Questions about timing within synchronized blocks

Discussion in 'Java' started by Robert Mark Bram, May 31, 2004.

  1. Hi All!

    I have some questions about timing with synchronization.. Which is better:

    Object sync;
    synchronized (sync){
    // Do important stuff..
    } // end synchronized

    or this:
    synchronized (sync){
    // Do important stuff..
    } // end synchronized

    In the first example, is there any chance that the timing will stuff up and
    when blocked threads get notified, Java still thinks control is in the
    synchronized section?

    If I do something like this:
    synchronized (sync){
    // Do important stuff..
    // Do more important stuff..
    } // end synchronized

    Obviously this is deadlock making code.. but what if "Do more important
    stuff" was just "i+=1".. could it still work then?

    Thanks for any advice!

    Robert Mark Bram, May 31, 2004
    1. Advertisements

  2. Robert Mark Bram

    Carl Howells Guest

    The second case will throw an IllegalMonitorStateException. (I think
    that's the name of the exception, anyway.) Calls to wait and
    notify[all] must be inside blocks synchronized on the object they're
    being called on.
    No. But see below. You are *very* confused.
    That code has no more chance of causing a deadlock than if all the
    important stuff was before the notifyAll call.

    You completely don't understand the semantics of wait and notify.
    (notifyAll is just a special case of notify, so I won't bother
    mentioning it explicitly further.)

    When you call wait on an object, you first must have that object's lock.
    (In other words, be in code that has synchronized on that object.)
    When wait is called, it does two things (initially). First, it
    *releases* the lock on the object it was called on. Second, it puts the
    current thread into a non-runnable (system dependent for the details,
    but whatever) state, and then execution moves to some other thread.

    When you call notify on an object, you first must have that object's
    lock. (Same as with wait). When notify is called, it does one thing
    directly, which is to put some thread (if any exist anyway) that is
    waiting on that object back into the runnable state. But notify doesn't
    cause the lock to be released in the current thread, nor does it cause
    the waiting thread to gain the lock. (This is the only spot notifyAll
    differs from notify, in that notifyAll performs that action for *all*
    waiting threads. But the difference is very minor, and typically notify
    does what you want anyway.)

    Then, the code that called notify continues executing. Any threads that
    were waiting attempt to regain the lock on the object they waited on.
    The wait() method won't actually return until that lock is re-acquired.
    So, the wait() call won't ever return for more than one thread
    simultaneously, and it won't ever return until the code that notified it
    leaves the synchronized block in which it acquired the lock for that
    object. (Or if it was a version of wait that had a timeout, and timed
    out, wait won't return until it reacquires the lock on the object, which
    may or may not be immediate, depending on whether there is contention
    for the lock.)

    In summary... Your first and third code samples are indistinguishable
    from the standpoint of execution behavior. The second code sample is
    just broken, because notify is called at an illegal time.
    Carl Howells, May 31, 2004
    1. Advertisements

  3. Hi Carl,

    Thank you for letting me know that notifyAll() outside a synchronized block
    is illegal.

    I found the answer I was looking for elsewhere (mental note: google first!):
    - an object entering the synchronized code will block (something like an
    implicit wait()) if it doesn't own the lock;
    - code leaving the synchronized block will wake up one waiting thread, if
    any (something like an implicit notifyAll();
    - I don't need any notify calls in the synchronized block because Java
    implicitly handles this.

    Robert Mark Bram, Jun 1, 2004
  4. Robert Mark Bram

    xarax Guest

    You only need the notify[All] calls when other threads
    have called wait() on the synchronized object. If you're
    intent is to create a critical section of code where only
    one thread at a time may "do important stuff" to the object,
    then you only need to synchronize on that object.

    OTOH, if other threads are waiting for work to do (like
    waiting on an event queue for a message object to arrive),
    then you need wait() and notify(). A thread that wants to
    pull a message from an event queue will wait() on that
    queue (when the queue is empty) for another thread to call
    notify() after it has placed a new message onto the queue.
    xarax, Jun 1, 2004
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.