Thread Synchronization

When two or more threads need access to a shared resource, only one thread can access the resource at a time. The process is called synchronization.

Using Synchronized Methods

You restrict the access to only one thread at a time by preceding call( )'s definition with the keyword synchronized:


class Shared {
  synchronized void call(String msg) {
    System.out.println("Start" );
    System.out.println(msg);
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      System.out.println("Interrupted");
    }
    System.out.println("end");
  }
}

class Caller implements Runnable {
  String msg;
  Shared target;
  Thread t;

  public Caller(Shared targ, String s) {
    target = targ;
    msg = s;
    t = new Thread(this);
    t.start();
  }

  public void run() {
    target.call(msg);
  }
}

public class Main {
  public static void main(String args[]) {
    Shared target = new Shared();
    Caller ob1 = new Caller(target, "A");
    Caller ob2 = new Caller(target, "B");

    try {
      ob1.t.join();
      ob2.t.join();
    } catch (InterruptedException e) {
      System.out.println("Interrupted");
    }
  }
}

The synchronized Statement

You put calls to the methods defined by this class inside a synchronized block. This is the general form of the synchronized statement:


synchronized(object) { 
// statements to be synchronized 
}

Here, object is a reference to the object being synchronized. A synchronized block ensures that a call to a method occurs only after the current thread has successfully entered object's monitor.

Here is an alternative version of the preceding example, using a synchronized block within the run( ) method:


class Share {
  void call(String msg) {
    System.out.println("start");
    System.out.println(msg);
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      System.out.println("Interrupted");
    }
    System.out.println("end");
  }
}

class Caller implements Runnable {
  String msg;
  Share target;
  Thread t;

  public Caller(Share targ, String s) {
    target = targ;
    msg = s;
    t = new Thread(this);
    t.start();
  }

  public void run() {
    synchronized (target) { // synchronized block
      target.call(msg);
    }
  }
}

public class Main {
  public static void main(String args[]) {
    Share target = new Share();
    Caller ob1 = new Caller(target, "A");
    Caller ob2 = new Caller(target, "B");
    try {
      ob1.t.join();
      ob2.t.join();
    } catch (InterruptedException e) {
      System.out.println("Interrupted");
    }
  }
}

An example of deadlock.


public class Main {
  private static Object lock1 = new Object();
  private static Object lock2 = new Object();

  public static void main(String[] args) {
    Thread thdA = new Thread(new Runnable() {
      @Override
      public void run() {
        while (true)
          synchronized (lock1) {
            synchronized (lock2) {
              System.out.println("first thread in instanceMethod1");
            }
          }
      }
    });
    
    Thread thdB = new Thread(new Runnable() {
      @Override
      public void run() {
        while (true)
          synchronized (lock2) {
            synchronized (lock1) {
              System.out.println("second thread in instanceMethod2");
             }
          }
      }
    });
    thdA.start();
    thdB.start();
  }
}
Home 
  Java Book 
    Thread Conncurrent  

Thread:
  1. Multithreaded Programming
  2. The Main Thread
  3. Thread Name
  4. Thread sleep
  5. Thread Creation
  6. isAlive( ) and join( )
  7. Thread Priorities
  8. Thread Synchronization
  9. Interthread Communication
  10. Suspending, Resuming, and Stopping Threads
  11. Handle Uncaught Exception
  12. ThreadLocal variables