public final synchronized void join(long millis) throwsInterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
How does wait(0) make the main thread wait until it finishes. Thread is calling wait on itself? As far as my understanding it must have a lock on itself to call wait() method? How does it notify the main thread when it finishes?
The documentation explains the logic:
This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
So this implementation relies on the fact that the Thread object does not just represent a thread, but is also an object like any other object in Java. As such, it inherits from Object, has its own monitor and can be synchronized, have threads waiting on it, etc.
It must have a lock on itself to call wait() method?
Yes. And indeed, this method is declared synchronized. So it synchronizes on the Thread instance itself. Once you are inside it, you have the Thread instance's monitor. Then when wait is called, you relinquish it, so other threads can do the same thing.
This might be a bit confusing. Your currently running thread is thread A. You are using join on thread B. The object being synchronized on here is the instance of thread B, and this causes thread A to wait until notifyAll is called on the same (B) instance.
When the thread B finishes, it calls notifyAll on its own instance. So any threads that are blocked in a wait on thread B's instance will be notified.
As far as my understanding it must have lock on itself to call wait() method?
Not on itself, but on the Thread object. And the caller does have a lock on the Thread object. Notice that t.join() is a synchronized method.
How does it notifies to the main thread when it finishes?
Don't get confused by the difference between a Thread and a thread. A Thread instance is a heap object that a program uses to start and manage the life-cycle of a thread of execution in the code. It's methods often are called by other threads than the one it is managing.
If thread A calls t.join(), it will lock the object t, and then it will call t.wait() as many times as it takes until the state of t is Thread.State.TERMINATED.
Remember that, inside each t.wait() call, the lock is released, and then re-acquired before the wait() returns.
In the thread that is managed by t, one of the very last things that it does is, it sets the state of t to TERMINATED, and then calls t.notify(). That will wake up thread A.
obj.wait() causes current thread to sleep, until some another thread call obj.notify() .
t.join() - causes current thread to wait until thread 't' finishes
Related
If I just use synchronized, not the wait/notify methods, will it still be thread-safe?
What's the difference?
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.
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();
}
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
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.
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.
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.
From jdk 1.7.0_45
The instance method of Thread.join(long miilliseconds) works by making the caller Thread wait on this Thread's Object monitor.Also,the javadoc explicitly states that
As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wai t(delay);
now = System.currentTimeMillis() - base;
}
}
}
I don't see notifyAll() getting called so that the Thread calling join() gets the monitor for this Thread's Object
If I am calling t.join(0) on thread t,then I am not implementing notifyAll() in my run() code.So how does the caller thread(the thread which calls t.join() gets notified)
The API documentation says (my emphasis):
Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.
This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
The join method is not responsible for the notification, it's the thing doing the waiting.
The notifying would be done by whatever JVM code is responsible for terminating the thread.
You must first understand the notify-wait mechanism. One thread waits (on an object) until another notifies it.
Example code
// in main thread
Thread t1 = new Thread(..);
t1.start();
t1.join();
The implementation of Thread#start() is native. The implementation is required to invoke notifyAll() once the Thread#run() method completes whether abruptly or normally.
This is required so that the thread calling join() can be notified.
In the example above, when the main thread calls join(), it eventually executes
wait(delay);
which is invoked on the Thread instance referenced by t1. This will cause the main thread to block until notify or notifyAll is invoked on the same Thread object which is what the native implementation of start must do, ie. invoke this.notifyAll() (probably implemented in native code).
This is also the reason why developers absolutely should not call wait and notify on Thread instances, so as not to mess with this join implementation.
I wrote a test app that should never stop. It issues t.wait() (t is a Thread object), but I never call notify. Why does this code end?
Despite the main thread synchronizing on t, the spawned thread runs, so it doesn't lock this object.
public class ThreadWait {
public static void main(String sArgs[]) throws InterruptedException {
System.out.println("hello");
Thread t = new MyThread();
synchronized (t) {
t.start();
Thread.sleep(5000);
t.wait();
java.lang.System.out.println("main done");
}
}
}
class MyThread extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
java.lang.System.out.println("" + i);
try {
Thread.sleep(500);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
The result is that the main thread waits 5 seconds and during this time worker gives its output. Then after 5 seconds are finished, the program exits. t.wait() does not wait. If the main thread wouldn't sleep for 5 seconds (commenting this line), then t.wait() would actually wait until the worker finishes. Of course, join() is a method to use here, but, unexpectedly, wait() does the same thing as join(). Why?
Maybe the JVM sees that, since only one thread is running, there is no chance to notify the main thread and solves the deadlock. If this is true, is it a documented feature?
I'm testing on Windows XP, Java 6.
You're waiting on a Thread - and while most objects aren't implicitly notified, a Thread object is notified when the thread terminates. It's documented somewhere (I'm looking for it...) that you should not use wait/notify on Thread objects, as that's done internally.
This is a good example of why it's best practice to use a "private" object for synchronization (and wait/notify) - something which only your code knows about. I usually use something like:
private final Object lock = new Object();
(In general, however, it's cleaner to use some of the higher-level abstractions provided by java.util.concurrent if you can. As noted in comments, it's also a good idea to implement Runnable rather than extending Thread yourself.)
The JavaDoc for wait gives the answer: spurious wakeups are possible. This means the JVM is free to end a call to wait whenever it wants.
The documentation even gives you a solution if you don't want this (which is probably always the case): put the call to wait in a loop and check whether the condition you wait for has become true after every wakeup.
I have 4 methods (m1, m2, m3 and m4) in a class. Method m1, m2 and m3 are synchronized methods. Also, I have 4 threads t1, t2, t3 and t4 respectively.
If t1 access the m1 method (synchronized method), could t2 thread access m2 method (synchronized method) simultaneously? If not what would be the state of t2?
If t1 access the m1 method (synchronized method), could t2 thread access m2 method (synchronized method) simultaneously?
The synchronized keyword applies on object level, and only one thread can hold the lock of the object. So as long as you're talking about the same object, then no, t2 will wait for t1 to release the lock acquired when it entered m1.
The thread can however release the lock without returning from the method, by calling Object.wait().
If not, what would be the state of t2 ?
It would sit tight and wait for t1 to release the lock (return from the method or invoke Object.wait()). Specifically, it will be in a BLOCKED state.
Thread state for a thread blocked waiting for a monitor lock. A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or reenter a synchronized block/method after calling Object.wait.
Sample code:
public class Test {
public synchronized void m1() {
try { Thread.sleep(2000); }
catch (InterruptedException ie) {}
}
public synchronized void m2() {
try { Thread.sleep(2000); }
catch (InterruptedException ie) {}
}
public static void main(String[] args) throws InterruptedException {
final Test t = new Test();
Thread t1 = new Thread() { public void run() { t.m1(); } };
Thread t2 = new Thread() { public void run() { t.m2(); } };
t1.start();
Thread.sleep(500);
t2.start();
Thread.sleep(500);
System.out.println(t2.getState());
}
}
Output:
BLOCKED
If the methods are synchronized on the same monitor, then they cannot execute simultaneously in different threads. When the second thread comes to the monitor entry (the start of the synchronized method in this case), it will block until the first thread releases the monitor.
The actual state of the blocked thread in this case, as reported by jconsole, will be something like java.lang.Thread.State: WAITING (on object monitor)
Assuming all methods are normal instance methods, then they will share the same monitor when invoked on the same object. That is, if you had something like:
// Thread 1
A a1 = new A();
a1.m1();
// Thread 2
A a2 = new A();
a2.m2()
then in this case, the second thread will be able to call the method, because it's trying to obtain the implicit monitor of the a2 object, which is not locked by thread 1. But if thread 2 tried to call a1.m2(), then it would block until thread 1 had finished executing m1().
If you have static methods, then they obtain the explicit monitor of the class itself (A.class in my hypothetical-naming case), so will not be blocked by any instance method invocations.
No, it couldn't. That's the only point there is to synchronized: different threads can't do these things simultaneously (You don't have to guard against the same thread doing them simultaneously, because a single thread can't do anything in parallel at all.) The state of the waiting thread is 'waiting for lock'. (With a sufficiently modern JVM you can actually have this state displayed on the console if you ask in the right way.)
If t1 access the m1 method (synchronized method), could t2 thread access m2 method (synchronized method) simultaneously?
No. Thread t2 will wait for Thread t1 to release the lock.
In your same example, t2 can access method m4 which is not synchronized.
Locks In synchronized Methods
Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them
When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception
Coming back to your second query:
If not, what would be the state of t2 ?
Thread t2 is in blocked state and waiting for Thread t1 to release the lock.
From java documentation page:
making synchronized method have 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 thread
Suppose a thread A is running. I have another thread, B, who's not. B has been started, is on runnable state.
What happens if I call: B.join()?
Will it suspend the execution of A or will it wait for A's run() method to complete?
join() will make the currently executing thread to wait for the the thread it is called on to die.
So - If A is running, and you call B.join(), A will stop executing until B ends/dies.
Join waits till the thread is dead. If you call it on a dead thread, it should return immediately. Here's a demo:
public class Foo extends Thread {
/**
* #param args
*/
public static void main(String[] args) {
System.out.println("Start");
Foo foo = new Foo();
try {
// uncomment the following line to start the foo thread.
// foo.start();
foo.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Finish");
}
public void run() {
System.out.println("Foo.run()");
}
}
From http://java.sun.com/docs/books/tutorial/essential/concurrency/join.html
The join method allows one thread to
wait for the completion of another. If
t is a Thread object whose thread is
currently executing,
t.join();
causes the current thread to pause
execution until t's thread terminates.
Overloads of join allow the programmer
to specify a waiting period. However,
as with sleep, join is dependent on
the OS for timing, so you should not
assume that join will wait exactly as
long as you specify.
I can strongly recommend the Java Tutorial as a learning resource.
Calling the join method on a thread causes the calling thread to wait for the thread join() was called on to finish. It does not affect any other threads that are not the caller or callee.
In your example, A would only wait for B to complete if you are calling B.join() from A. If C is calling B.join(), A's execution is unaffected.
I think that if A is the current thread running. A call to B.join() will suspend it until B's run() method completes. Is this correct?
Whichever thread you call B.join() from will block and wait for B to finish.