Difference between Synchronized block with wait/notify and without them?
Asked Answered
S

6

24

If I just use synchronized, not the wait/notify methods, will it still be thread-safe?

What's the difference?

Selffulfillment answered 20/10, 2011 at 21:6 Comment(0)
U
18

Using synchronized makes a method / block accessible by only on thread at a time. So, yes, it's thread-safe.

The two concepts are combined, not mutually-exclusive. When you use wait() you need to own the monitor on that object. So you need to have synchronized(..) on it before that. Using .wait() makes the current thread stop until another thread calls .notify() on the object it waits on. This is an addition to synchronized, which just ensures that only one thread will enter a block/method.

Unrestrained answered 20/10, 2011 at 21:9 Comment(2)
so why do we need use wait/notify methods? there must be some differences, right ?Selffulfillment
I think when synchronized block ends, it will release the lock. Other thread who executes synchronized method or statement will block when it cannot get the lock. It is also acts like a wait() notify() mechanism,very similar. Alan is asking what is the difference of having wait() and notify() than just normal synchronized block ends.Daiquiri
M
19

So after just being embarrassed in an interview question on this I decided to look it up and understand it again for 1 billionth time.

synchronized block makes the code thread safe. No doubt about that. When wait() and notify() or notifyAll() come in is where you are trying to write more efficient code. For example, if you have a list of items that multiple threads share then if u put it in synchronized block of a monitor then threads threads will constantly jump in and run the code back and forth, back and forth during context switches......even with an empty list!

The wait() is hence used on the monitor (the object inside the synchronized(..)) as a mechanism to to tell all threads to chill out and stop using cpu cycles until further notice or notifyAll().

so something like:

synchronized(monitor) {
    if( list.isEmpty() )
        monitor.wait();
}

...somewhere else...

synchronized(monitor){
    list.add(stuff);
    monitor.notifyAll();
}
Musclebound answered 26/11, 2012 at 20:1 Comment(5)
It is dictated that you always call wait() inside a loop, e.g. while ( list.isEmpty() ) monitor.wait() if you want to wait until there is actually something put inside the list by another thread. docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait()Villareal
This should be the answer. Programmer can not choose which synchronized block should go first. But wait/notify can guide which block should go first. +1.Tread
If one thread has gotten the lock on the monitor and is working with it, how will the second thread get the lock on monitor to go inside the synchronized block to wait?Tullis
"understand it again for 1 billionth time". I feel you.Herman
@experimentunit1998X Each thread "waits" itself. When the owner of the lock calls wait(), it releases this lock. So another thread disputing to enter the synchronized block can enter.Aronarondel
U
18

Using synchronized makes a method / block accessible by only on thread at a time. So, yes, it's thread-safe.

The two concepts are combined, not mutually-exclusive. When you use wait() you need to own the monitor on that object. So you need to have synchronized(..) on it before that. Using .wait() makes the current thread stop until another thread calls .notify() on the object it waits on. This is an addition to synchronized, which just ensures that only one thread will enter a block/method.

Unrestrained answered 20/10, 2011 at 21:9 Comment(2)
so why do we need use wait/notify methods? there must be some differences, right ?Selffulfillment
I think when synchronized block ends, it will release the lock. Other thread who executes synchronized method or statement will block when it cannot get the lock. It is also acts like a wait() notify() mechanism,very similar. Alan is asking what is the difference of having wait() and notify() than just normal synchronized block ends.Daiquiri
S
5

Making method as synchronized has two effects:

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.

synchronization help you to guard the critical code.

If you want to establish communication between multiple threads, you have to use wait() and notify()/notifyAll()

wait(): Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.

notify(): Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened.

notifyAll():Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods.

Simple use case for using wait() and notify() : Producer and Consumer problem.

Consumer thread has to wait till Producer thread produce data. wait() and notify() are useful in above scenario. Over a period of time, better alternatives have been introduced. Refer to this high level concurrency tutorial page.

In simple terms:

Use synchronized to guard protect critical section of your data and guard your code.

Use wait() and notify() along with synchronization if you want to establish communication between multiple threads in safe manner, which are interdependent on each other.

Related SE questions:

What does 'synchronized' mean?

A simple scenario using wait() and notify() in java

Seligman answered 29/8, 2016 at 7:36 Comment(0)
W
3

Effective Java item 69: "Given the difficulty of using wait and notify correctly, you should use the higher-level concurrency utilities instead."

Avoid using wait() and notify(): use synchronized, or other utilities from java.util.concurrent, when possible.

Witless answered 20/10, 2011 at 21:32 Comment(0)
D
0

Synchronised block is used, if 2 threads of "same object" tries to accquire the lock. Since object class holds the lock, it knows who to give. Whereas, if 2 threads(say t2 and t4) of 2 objects( t1 & t2 of obj1 and t3 & t4 of obj 2) try to acquire the lock, obj1 would be unaware of obj2's lock and obj2 would be unaware of obj1's lock. Hence wait and notify methods are used.

eg:

//example of java synchronized method  
class Table{  
 synchronized void printTable(int n){//synchronized method  
   for(int i=1;i<=5;i++){  
     System.out.println(n*i);  
     try{  
      Thread.sleep(400);  
     }catch(Exception e){System.out.println(e);}  
   }  

 }  
}  

class MyThread1 extends Thread{  
Table t;  
MyThread1(Table t){  
this.t=t;  
}  
public void run(){  
t.printTable(5);  
}  

}  
class MyThread2 extends Thread{  
Table t;  
MyThread2(Table t){  
this.t=t;  
}  
public void run(){  
t.printTable(100);  
}  
}  

public class TestSynchronization2{  
public static void main(String args[]){  
Table obj = new Table();//only one object  
MyThread1 t1=new MyThread1(obj);  
MyThread2 t2=new MyThread2(obj);  
t1.start();  
t2.start();  
}  
} 

Two threads t1 and t2 belongs to same object, hence synchronization works fine here. Whereas,

class Table{  
 synchronized void printTable(int n){//synchronized method  
   for(int i=1;i<=5;i++){  
     System.out.println(n*i);  
     try{  
      Thread.sleep(400);  
     }catch(Exception e){System.out.println(e);}  
   }  

 }  
}  

class MyThread1 extends Thread{  
Table t;  
MyThread1(Table t){  
this.t=t;  
}  
public void run(){  
t.printTable(5);  
}  

}  
class MyThread2 extends Thread{  
Table t;  
MyThread2(Table t){  
this.t=t;  
}  
public void run(){  
t.printTable(100);  
}  
}  

public class TestSynchronization2{  
public static void main(String args[]){  
Table obj = new Table();
Table obj1 = new Table();
MyThread1 t1=new MyThread1(obj);  
MyThread2 t2=new MyThread2(obj1);  
t1.start();  
t2.start();  
}  
} 

When you run the above program, synchronisation does not work since each thread belong to different object, Hence you should use wait and notify here.

Dodson answered 13/10, 2014 at 20:42 Comment(0)
M
0

wait/notify is required when you want to wait for some condition (e.g. user input) INSIDE a synchronized block.

Typical usage:

synchronized(obj) {
    // do something

    while(some condition is not met) {
        obj.wait();
    }
    // do something other
}

Let's assume that you don't use wait(). Then, you have to implement busy loop polling the condition that you want, which is bad for performance.

synchronized(obj) {
    // do something

    while(some condition is not met) { // busy loop }

    // do something other
}

Important note: Even though a thread is awaken by notify() or notifyAll() from other thread, the awaken thread does NOT guaranteed to immediately resume its execution. If there were other threads awaiting to execute a synchronized block on the same object, then the awaken thread should compete with the threads.

Melodimelodia answered 28/8, 2016 at 9:30 Comment(1)
I'm not sure this is a good example. wait() is a blocking method, so it does not have to be inside an infinite loop. You could simply use wait() in one synchronized block, and when your condition is met, you could use notify() in another synchronized block to "unblock" the wait() method.Unsaid

© 2022 - 2024 — McMap. All rights reserved.