User27854
User27854

Reputation: 884

Issues on using synchronized method

I am trying to understand synchronization, but while it tried to implement it,I am getting an ambiguous result, while trying to implement synchronized, Have a look at it.

By obesrving the output, it is clear that two threads are able to access the synchronized block simultaneously. Guide me where am I Going wrong.

Output:

Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0

Program:

package com.StackOverFlow.Doubts3;

public class Dbts5 {
public static void main(String[] args) {

    Display d1= new Display();
    MyThreads th1= new MyThreads(d1, "Thread1");

    th1.start();

    MyThreads th2= new MyThreads(d1, "Thread2");

    th2.start();




}
}

class MyThreads extends Thread{


Display d;
String name;


@Override
public void run() {
    super.run();
    for (int i = 0; i < 10; i++) {
        d.show();   
    }



}

public MyThreads() {}

MyThreads(Display d, String name){
    this.d=d;
    this.name=name;
}


}

class Display{

synchronized void show(){
    System.out.println("Display class show method called by- "+Thread.currentThread().getName());
    try {
        Thread.currentThread().sleep(300);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}
}

(Edited) Expected output:

Display class show method called by- Thread-0
Display class show method called by- Thread-0
Display class show method called by- Thread-0
.
.
.
Display class show method called by- Thread-1
Display class show method called by- Thread-1
Display class show method called by- Thread-1

Upvotes: 1

Views: 134

Answers (3)

Jean Logeart
Jean Logeart

Reputation: 53879

Your synchronized block is not accessed concurrently.

What you observe is:

  • Thread-0 gets in and out 7 times
  • Thread-1 gets in and out 10 times
  • Thread-0 gets in and out 3 times

If you add some trace, you will see better that show is never entered twice before exiting:

synchronized void show(){
    System.out.println(Thread.currentThread().getName() + " In");
    // do show
    System.out.println(Thread.currentThread().getName() + " Out");
}

And you will see:

Thread-0 In
Display class show method called by- Thread-0
Thread-0 Out
// ...
Thread-1 In
Display class show method called by- Thread-1
Thread-1 Out
// ...
Thread-0 In
Display class show method called by- Thread-0
Thread-0 Out

If you want the threads to call show n times before releasing the lock, then you should use synchronized around the for-loop:

@Override
public void run() {
    showSeveralTimes(10);
}

And in Display:

synchronized void showSeveralTimes(int n) {
    for(int i = 0 ; i < n ; ++i) {
        show();
    }
}

Upvotes: 2

meskobalazs
meskobalazs

Reputation: 16051

Quoting from an Oracle tutorial:

  • First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
  • Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.

So Thread-n runs, returns, Thread-n runs, returns, ad infinitum (or 10 in this case)

Upvotes: 0

NPE
NPE

Reputation: 500953

By obesrving the output, it is clear that two threads are able to access the synchronized block simultaneously.

No, there's absolutely no evidence of that. Let's consider the following output:

Display class show method called by- Thread-0
Display class show method called by- Thread-1

Here:

  • Thread-0 calls show(), enters the synchronized block, prints out the message, exits from show() (leaving the synchronized block).
  • Thread-1 calls show(), enters the synchronized block, prints out the message, exits from show() (leaving the synchronized block).

and so on.

If you want to see the threads blocking each other, put synchronized around the loop:

synchronized(d) {
    for (int i = 0; i < 10; i++) {
        d.show();   
    }
}

Upvotes: 2

Related Questions