tez
tez

Reputation: 5290

Thread Synchronization Behaviour

class Untitled {
    public static void main(String[] args) {
        MyRunnable r1 = new MyRunnable();
        Thread t1 = new Thread(r1,"Thread 1:");
        Thread t2 = new Thread(r1,"Thread 2:");
        t1.start();
        t2.start();

    }
}

class MyRunnable implements Runnable
{
    String s1 = "Hello World";
    String s2 = "Hello New World";
    public void run()
    {
        synchronized(s1)
        {
            for(int i =0;i<3;++i)
            System.out.println(Thread.currentThread().getName()+s1);

        }
        synchronized(s2)
        {
            for(int i = 0;i<3;++i)
            System.out.println(Thread.currentThread().getName()+s2);
        }

    }
}

OUTPUT:

Thread 1:Hello World
Thread 1:Hello World
Thread 1:Hello World
Thread 1:Hello New World
Thread 2:Hello World
Thread 1:Hello New World
Thread 2:Hello World
Thread 1:Hello New World
Thread 2:Hello World
Thread 2:Hello New World
Thread 2:Hello New World
Thread 2:Hello New World

Why can't Thread2 execute the second synchronized block in the run() method when Thread1 is executing the first synchronized block even though lock objects are different.Does Thread2's execution wait at the first synchronized block till Thread1 leaves that block??

If so how to make both synchronized blocks run concurrently??

Upvotes: 1

Views: 238

Answers (7)

Abhishek Kumar
Abhishek Kumar

Reputation: 219

class ThreadExample {
    public static void main(String[] args) {
        MyRunnable15756 r1 = new MyRunnable15756();
        Thread t1 = new Thread(r1,"Thread 1:");
        Thread t2 = new Thread(r1,"Thread 2:");
        t1.start();
        t2.start();

    }
}

class MyRunnable15756 implements Runnable
{
    String s1 = "Hello World";
    String s2 = "Hello New World";
    Runnable runnable1 =  new Runnable(){
        @Override
        public void run() {
              synchronized(s1)
                {
                    for(int i =0;i<30;++i)
                    System.out.println(Thread.currentThread().getName()+s1);

                }

        }
    };

    Runnable runnable2 =  new Runnable(){
        @Override
        public void run() {
             synchronized(s2)
                {
                    for(int i = 0;i<30;++i)
                    System.out.println(Thread.currentThread().getName()+s2);
                }

        }
    };
    public void run()
    {

        new Thread(runnable1).start();

        new Thread(runnable2).start();



    }
}

Upvotes: 0

OldCurmudgeon
OldCurmudgeon

Reputation: 65793

Here's an example of getting them both to run concurrently. Note that not only have I put each loop in a separate thread but I have reduced the scope of the synchronization to just the print.

public class Test {
  static class MyRunnable implements Runnable {
    final String s1 = " Hello World - ";
    final String s2 = " Hello New World - ";
    static final int n = 10;

    @Override
    public void run() {
      // Two loops in two threads.
      new Thread(new Runnable() {
        @Override
        public void run() {
          for (int i = 0; i < n; ++i) {
            // Scope reduced.
            synchronized (s1) {
              System.out.println(Thread.currentThread().getName() + s1 + i);
            }
          }
        }
      }, Thread.currentThread().getName() + "(a)").start();
      // Two loops in two threads.
      new Thread(new Runnable() {
        @Override
        public void run() {
          for (int i = 0; i < n; ++i) {
            // Scope reduced.
            synchronized (s2) {
              System.out.println(Thread.currentThread().getName() + s2 + i);
            }
          }
        }
      }, Thread.currentThread().getName() + "(b)").start();
    }
  }

  public void test() {
    MyRunnable r1 = new MyRunnable();
    Thread t1 = new Thread(r1, "Thread 1:");
    Thread t2 = new Thread(r1, "Thread 2:");
    t1.start();
    t2.start();
  }

  public static void main(String args[]) {
    new Test().test();
  }
}

Upvotes: 0

Abhishek Kumar
Abhishek Kumar

Reputation: 219

It is simply the compiler execute the code i.e. compiler execute code in sequence the way they are written. thread 2 cannot skip first block of code. it will first execute first block then others.

Upvotes: 1

Pheonix
Pheonix

Reputation: 6052

Why can't Thread2 execute the second synchronized block in the run() method when Thread1 is executing the first synchronized block

Code is executed line by line, The execution doesnt jump to next block and Thread 2 waits for Thread 1 to leave the 1st Synchronized block.

Does Thread2's execution wait at the first synchronized block till Thread1 leaves that block

Yes.

If so how to make both synchronized blocks run concurrently??

So keep them In seperate Runnable Instances. and Not one after the other in a Sequence.

Upvotes: 3

phoenix7360
phoenix7360

Reputation: 2907

The two blocks are one after the other, which means that Thread 2 has to go though block 1 before going through block 2

Upvotes: 3

assylias
assylias

Reputation: 328568

Does Thread2's execution wait at the first synchronized block till Thread1 leaves that block??

Yes that's the idea - thread2 executes the blocks one after the other. If it is blocked and can't enter the first one, it will wait there until the s1 lock becomes available.

If so how to make both synchronized blocks run concurrently??

You would need to split them in two different runnables and use one thread for each.

Upvotes: 6

Subhrajyoti Majumder
Subhrajyoti Majumder

Reputation: 41200

Because within the run method statements are executed in sequentially not parallely.

So who ever Thread 1 or Thread 2 acquire the lock of s1 other will wait untill it is released.

Upvotes: 3

Related Questions