Working of Java wait method - java

I have the following code:
public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
ThreadImpl thr = new ThreadImpl();
thr.start();
Thread.sleep(1000);
synchronized(thr){
System.out.println( "MAIN "+thr.hashCode());
System.out.println("Main -->got the lock");
thr.wait();
System.out.println("Main -->Done with waiting");
}
}
}
class ThreadImpl extends Thread{
public synchronized void sayHello(){
System.out.println("Ssay hello ");
}
#Override
public void run() {
synchronized(this){
System.out.println( "METHOD "+this.hashCode());
System.out.println("METHOD Got the lock ");
System.out.println("METHOD Going for sleep ");
for(int i =0;i< 100000;i++);
try {
Thread.sleep(2000);
System.out.println("METHOD Woke up ");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("METHOD Done leaving the thread");
}
}
}
In the main method of ThreadDemo, I am creating a thread object ThreadImpl and starting it. Next, the main thread sleeps for 1000ms.
The run method of the thread will be executed in a separate thread.As part of this it loops 100000 times and sleeps for 2000ms. Then it exits the method.
The main thread wakes up and acquires the lock for "thr" and then goes on wait state. As the other thread has completed its execution, this wait should be forever. However, I see the following result:
METHOD 1729414014
METHOD Got the lock
METHOD Going for sleep
METHOD Woke up
METHOD Done leaving the thread
MAIN 1729414014
Main -->got the lock
Main -->Done with waiting
How is it that the main method continues its execution when no one has notified it?

This is spurious wake-up, see jls:
The thread may be removed from the wait set due to any one of the
following actions, and will resume sometime afterward:
A notify action being performed on m in which t is selected for removal from the wait set.
A notifyAll action being performed on m.
An interrupt action being performed on t.
If this is a timed wait, an internal action removing t from m's wait set that occurs after at least millisecs milliseconds plus
nanosecs nanoseconds elapse since the beginning of this wait
action.
An internal action by the implementation. Implementations are permitted, although not encouraged, to perform "spurious wake-ups", that is, to remove threads from wait sets and thus enable resumption without explicit instructions to do so.

Related

Main thread does not seem to be interrupted

in my Java program main thread does not get interrupted. Why?
/*
* This class counts till infinity
*/
class infinityT extends Thread{
int counter = 0;
public void run(){
try{
while(true){
if(counter>500){
// this class will throw compilation error here as Thread.sleep is not a valid method here as it does not extend Thread class
Thread.sleep(1000);
}
System.out.println(counter++);
}
}catch(InterruptedException e){
System.out.println("infinity Interrupted: "+counter);
}
}
}
class interruption{
public static void main(String args[]){
Thread t = new Thread(new infinityT());
// start the thread
t.start();
try{
// main thread does not seem to interrupt
Thread.currentThread().interrupt();
Thread.sleep(2000);
}catch(InterruptedException e){
System.out.println("Main thread interrupted!");
}
t.interrupt();
}
}
Output:
...
...
499
500
infinity Interrupted: 501
Your main thread does get interrupted but what it doesn't do is sleep when you call Thread.sleep() because you've already set its interrupted flag. Hence, all or most of the numbers would get printed after the Main thread interrupted! message.
If you scroll up the console (you may have to increase its buffer or just reduce the loop count to 10 or something) you should see it getting printed as well.
As an aside, you do not need to extend Thread to call sleep() as it's a static method. Or, you can simply start infinityT directly instead of passing it as Runnable again.
main thread gets interrupted, you might have missed it among the other outputs. check carefully and if u execute the same program multiple times, see the position in which the Main thread gets interrupted

Sleep() method on already sleeping thread

I am working on multi threading and i got a question regard thread sleep method. when i execute sleep()(with time t1) method on already in sleeping thread(with time t2). The total sleep time is t1+t2 or t2(if t2 > t1) or t1 (if t1 > t2):
code:
my thread class:
public class SampleThread extends Thread
{
public SampleThread(String msg)
{
super(msg);
start();
}
public void run()
{
try
{
SampleThread.sleep(1000);
System.out.
println("slept for run");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.
println("extends Thread Class is exited");
}
}
my main method :
public class TestThreads {
public static void main(String[] args) {
SampleThread st = new SampleThread("Extends Thread");
some(st);
System.out.println("main thread Executed");
}
public static void some(SampleThread t2 ){
try {
t2.sleep(10000);
System.out.println("slept for some" );
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
result:
slept for run
extends Thread Class is exited
slept for some
main thread Executed
from the result i can say that because sleep time for t2.sleep(10000) is more than SampleThread.sleep(1000) run() method exited first than main method.
But my question is how much time.
Sleep is called by currently running thread, it is not called on the thread object. So your sleep inside run methods pause the Sample thread, the one in the some method pauses your main thread (the one that started the program). Two different execution processes.
The sleep method is actually a static method of the Thread (and you are even calling it as such), which should already indicate for you, that it is not 'bound' to the thread object.
You cannot call sleep twice in the same thread, as to call it has to be awaked. There is no issue of additivity or priority.
So in your code, the second thread starts, executes its run method and pause for shorter time. In the meantime, the main thread continues and pauses for a long time, while the main thread sleeps the created thread finishes its sleeping and then terminates.
You have two different threads and neither blocks each other. So the one thread will wait for 10 seconds, and the other waits for 1 second. The total time you waited depends on which thread you cared about.
Your main waited 10 seconds, it doens't care if the other thread waits for 1 second or a million seconds (if the second thread is set as a daemon thread so it doesn't block the current app).
If your main app spins up a thread that is a daemon, it won't exit until all non-daemon threads are complete. In which case your main app will do its work, and then at the very last line it'll wait until those threads are done.
You can't execute sleep on a sleeping thread because sleep is a static method and can only cause the current thread to sleep.
t2.sleep(10000); causes the main thread to sleep, not t2. It's the same as Thread.sleep(10000).

Synchronized blocks don't work when using member of unrelated class as lock object?

Pretty much all resources I've found on synchronized blocks use this or a member of the class as a lock object. I'm interested in finding out why I can't get synchronized blocks to work when the lock object is a (static) member of another class. Here's my code to illustrate the problem:
public class Test {
public static void main(String[] args) {
Thread thread1 = new FirstThread();
Thread thread2 = new SecondThread();
thread1.start();
thread2.start();
}
}
class FirstThread extends Thread {
#Override
public void run() {
synchronized (Lock.lock) {
System.out.println("First thread entered block");
try {
Lock.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("First thread exited block");
}
}
class SecondThread extends Thread {
#Override
public void run() {
try {
Thread.sleep(1000); //just making sure second thread enters synch block after first thread
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (Lock.lock) {
System.out.println("Second thread entered block");
Lock.lock.notifyAll();
}
System.out.println("Second thread exited block");
}
}
class Lock {
public static Object lock = new Object();
}
My understanding is that the second thread should not be able to enter the synchronized block until the first thread exits, since they are synchronized on the same object. Thus I was expecting the program to hang (deadlock?) after "First thread entered block", since the second thread can't enter the block and the first thread will be stuck waiting for a notification. But instead I got the following output:
First thread entered block
Second thread entered block
Second thread exited block
First thread exited block
Clearly the second thread enters the synchronized block before the first thread has left it's block. Can someone explain what I'm missing?
I thought the purpose of synchronized blocks was to prevent exactly this. Is it because the lock object is a member of another class?
first thread Lock.lock.wait() relinquish the lock on the synchronized object so other thread can enter the critical path and wake up the waiters.
note that sleep(), instead, does not.
Difference between wait() and sleep()
Quote from the javadoc of Object.wait():
The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method.
If that was not the case, waiting would systematically cause a deadlock, since no thread would ever be able to enter the synchronized section needed to call notify() or notifyAll(), making wait and notify completely useless.
When you call lock.wait you "release ownership of this monitor". This allows thread 2 to enter the synchronized block.

Why is that sleeping inside a thread causes problems with `notify`?

Driver.java
public class Driver {
static Object obj = new Object();
public static void main(String [] args) throws InterruptedException
{
Thread thr = new Thread(new Runnable(){
#Override
public void run() {
System.out.println("Thread 1: Waiting for available slot.");
synchronized(obj){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 1: Found slot!");
long x = 0;
while(x < Integer.MAX_VALUE) x++;
System.out.println("Thread 1: Completed processing.");
System.out.println("Thread 1: Notifying other waiting threads.");
obj.notify();
}
}
});
Thread thr2 = new Thread(new Runnable(){
#Override
public void run() {
System.out.println("Thread 2: Waiting for available slot.");
synchronized(obj){
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread 2: Found slot!");
long x = 0;
while(x < Integer.MAX_VALUE) x++;
System.out.println("Thread 2: Completed processing.");
System.out.println("Thread 2: Notifying other waiting threads.");
obj.notify();
}
}
});
thr.start();
thr2.start();
System.out.println("Main Thread: All processing units busy.");
// Thread.sleep(2000); // Enable this and disable the other Thread.sleep(...) and NOW we are good. But again, 'why?' is the question.
synchronized(obj){
Thread.sleep(2000); // This causes a failure. Move it outside the synchronized and it will work why?
System.out.println("Main Thread: Found ONLY 1 available slot.");
obj.notify();
obj.wait(); // JVM should catch this as the last request so it has the least priority.
System.out.println("Main Thread: Finished and exiting...");
}
}
}
The code above will not notify the Threads because of the following line:
Thread.sleep(2000); // This causes a failure. Move it outside the synchronized and it will work why?
Please take a look at this line in context with the whole class. I am having hard time pinpointing to the reason why this simple proof-of-concept would fail if that line is placed inside ther synchronized block in the Main Thread.
Thank you
The problem is not the sleep but rather that the main thread almost always acquires the lock before one (and occasionally both) of the created threads does. If you print just inside the synchronized blocks it's much more clear what is going on:
synchronized(obj) {
System.out.println("this thread acquired the lock");
You'll see the output is almost always Thread #1, then the main thread, and finally Thread #2 after Thread #1 completes (but main has already returned).
If you run it enough times sometimes both child threads do acquire the lock first and it completes.
The reason moving the sleep to outside the synchronized block in the main thread works is it allows both child threads to reach their respective wait statements.
Read the doc.
Wakes up a single thread that is waiting on this object's
monitor.
If it is sleeping then it is not waiting.
There is other related problem, it is not possible to reach the notify line while the other thread is in the sleep as it keeps the monitor (lock) and the other thread can't run inside the synchronized block. This is always that way as both wait and notify must be run inside related syncrhonized blocks (against the same monitor).
sleep holds the lock, but wait doesn't. so when your main thread is sleeping, both thr and thr2 can't get the lock until main thread notifies them. At that moment, they start to wait and can't receive any notify()
The problem is that sleep does not release the monitor, that is: while the main thread is sleeping, all the other threads cannot enter the synchronized block, so they are basically sleeping with the main thread.
The moment the main thread wakes up, it does notify, but since no one yet entered the wait() position, no one is listening. Then the main thread waits and therefore releases the monitor, so now all threads can proceed to the wait() state, but no one is left to wake them up. -> Deadlock

Java wait()/join(): Why does this not deadlock?

Given the following Java code:
public class Test {
static private class MyThread extends Thread {
private boolean mustShutdown = false;
#Override
public synchronized void run() {
// loop and do nothing, just wait until we must shut down
while (!mustShutdown) {
try {
wait();
} catch (InterruptedException e) {
System.out.println("Exception on wait()");
}
}
}
public synchronized void shutdown() throws InterruptedException {
// set flag for termination, notify the thread and wait for it to die
mustShutdown = true;
notify();
join(); // lock still being held here, due to 'synchronized'
}
}
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
try {
Thread.sleep(1000);
mt.shutdown();
} catch (InterruptedException e) {
System.out.println("Exception in main()");
}
}
}
Running this will wait for one second and then properly exit. But that is unexpected to me, I expect a dead-lock to happen here.
My reasoning is as follows: The newly created MyThread will execute run(), which is declared as 'synchronized', so that it may call wait() and safely read 'mustShutdown'; during that wait() call, the lock is released and re-acquired upon returning, as described in the documentation of wait(). After one second, the main thread executes shutdown(), which is again synchronized as to not access mustShutdown at the same time as it's being read by the other thread. It then wakes up the other thread via notify() and the waits for its completion via join().
But in my opinion, there's no way that the other thread can ever return from wait(), since it needs to re-acquire the lock on the thread object before returning. It cannot do so because shutdown() still holds the lock while inside join(). Why does it still work and exit properly?
join() method internally calls wait() which will result in releasing of the lock(of Thread object).
See the code of join() below:
public final synchronized void join(long millis)
throws InterruptedException {
....
if (millis == 0) {
while (isAlive()) {
wait(0); //ends up releasing lock
}
}
....
}
Reason why your code sees this and not seen in general:: The reason why your code see this and not is not observed in general, is because the join() method waits() on Thread object itself and consequently relinquishes lock on the Thread object itself and as your run() method also synchronizes on the same Thread object, you see this otherwise unexpected scenario.
The implementation of Thread.join uses wait, which lets go of its lock, which is why it doesn't prevent the other thread from acquiring the lock.
Here is a step-by-step description of what happens in this example:
Starting the MyThread thread in the main method results in a new thread executing the MyThread run method. The main Thread sleeps for a whole second, giving the new Thread plenty of time to start up and acquire the lock on the MyThread object.
The new thread can then enter the wait method and release its lock. At this point the new thread goes dormant, it won't try to acquire the lock again until it is woken up. The thread does not return from the wait method yet.
At this point the main thread wakes up from sleeping and calls shutdown on the MyThread object. It has no problem acquiring the lock because the new thread released it once it started waiting. The main thread calls notify now. Entering the join method, the main thread checks that the new thread is still alive, then waits, releasing the lock.
The notification happens once the main thread releases the lock. Since the new thread was in the wait set for the lock at the time the main thread called notify, the new thread receives the notification and wakes up. It can acquire the lock, leave the wait method, and finish executing the run method, finally releasing the lock.
The termination of the new thread causes all threads waiting on its lock to receive a notification. This wakes up the main thread, it can acquire the lock and check that the new thread is dead, then it will exit the join method and finish executing.
/**
* Waits at most <code>millis</code> milliseconds for this thread to
* die. A timeout of <code>0</code> means to wait forever.
*
* #param millis the time to wait in milliseconds.
* #exception InterruptedException if any thread has interrupted
* the current thread. The <i>interrupted status</i> of the
* current thread is cleared when this exception is thrown.
*/
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;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
To complement the other answers: I see no mention of join() releasing any locks in the API-documentation, so this behavior is actually implementation-specific.
Learn from this:
don't subclass Thread, instead use a Runnable implementation passed to your thread object.
don't synchronize/wait/notify on objects you don't "own", e.g. where you don't know who else might synchronize/wait/notify on it.

Categories