views:

119

answers:

3

I have a method shout() with a synchronized block.

  private void shout(){
    System.out.println("SHOUT " + Thread.currentThread().getName());
    synchronized(this){
      System.out.println("Synchronized Shout"  + Thread.currentThread().getName());
      try {
        Thread.sleep(50);
      }
      catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println("Synchronized Shout"  + Thread.currentThread().getName());
     }
  }

If I have two Threads that run this method, am I correct in assuming that the two "Synchronized Shout" will always appear one after the other? There can be no other statements in between the "Synchronized Shout"?

+2  A: 

So long as the this reference is the same. If you run the code on two different objects, the lock will have no effect.

Note, if you were to use Object.wait on this instead of calling Thread.sleep to delay, then the lock would be removed (and reacquired before moving on).

Tom Hawtin - tackline
+2  A: 

Since the line that prints "SHOUT..." does not require a lock, it can appear at any point. Thus, even if one thread is holding the lock, another thread may come in and print "SHOUT...".

The following code shows the interleaving:

public class Interleave {
  public static void main(String[] args) throws Throwable {
    Task task = new Task();
    Thread t1 = new Thread(task);
    Thread t2 = new Thread(task);
    t1.start();
    Thread.sleep(25);
    t2.start();
  }

  private static class Task implements Runnable {
    public void run() {
      shout();
    }

    private void shout() {
      System.out.println("SHOUT " + Thread.currentThread().getName());
      synchronized (this) {
        System.out.println("Synchronized Shout "  + Thread.currentThread().getName());
        try {
          Thread.sleep(50);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        System.out.println("Synchronized Shout "  + Thread.currentThread().getName());
      }
    }
  }
}

It prints out

SHOUT Thread-0
Synchronized Shout Thread-0
SHOUT Thread-1
Synchronized Shout Thread-0
Synchronized Shout Thread-1
Synchronized Shout Thread-1
sjlee
I do not understand the point of the synchronized block then.
kunjaan
@kunjaan Synchronization does provide "mutual exclusion". But an extremely important point is that mutual exclusion is only among threads that participate in the SAME LOCK. Progress of any thread that does not participate in the same lock is unaffected. Therefore, any thread that executes a region of code that does not require acquiring the same lock (like the line that prints "SHOUT..." which is outside the synchronized block) is not affected by locking at all. By the same token, any thread that tries to acquire a different object lock is also unaffected (what Tom Hawtin points out).
sjlee
A: 

When two or more threads are running against the same instance, then the SHOUT can appear anywhere, because it's outside the synchronized block, and thus unguarded. The "synchronized shout"s will always appear strictly in order, with no synchornized shout from another thread getting in between and affecting the order.

mdma