I am writing a program to test how a thread can keep waiting if another thread has acquired lock on same object but after looking at output I am not sure how locking works in java. Here is what i have written:
public class Locking {
synchronized void methodA() {
System.out.println("inside A , " + Thread.currentThread().getName());
}
public static void main(String[] args) throws InterruptedException {
new Locking().execute();
}
private void execute() throws InterruptedException {
Thread t1 = new Thread(new MyThread());
t1.setName("t1");
Thread t2 = new Thread(new MyThread());
t2.setName("t2");
t1.start();
Thread.sleep(5000);
t2.start();
}
class MyThread implements Runnable {
#Override
public void run() {
while (true) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
methodA();
}
}
}
}
I expected thread t2 to be waiting forever and program will print only
inside A , t1
but when i run the program , I get following output:
inside A , t1
inside A , t2
Can anyone explain what is going on here?
I am writing a program to test how a thread can keep waiting if
another thread has acquired lock on same object
The single lock is here :
synchronized void methodA() {
System.out.println("inside A , " + Thread.currentThread().getName());
}
It takes the locks on the current instance but no statement in your code locks in a way where a thread could wait forever the lock.
Look at my comments :
#Override
public void run() {
while (true) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// the lock is set here
methodA();
// and that is released here
}
}
Make the synchronized method never releases the lock and only one of the thread will be able to enter in :
synchronized void methodA() {
while (true) {
System.out.println("inside A , " + Thread.currentThread()
.getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// handle it
}
}
}
prints :
inside A , t1
inside A , t1
inside A , t1
...
Her are some other examples to play with threads.
Replace sleep() by wait() and the current thread will release the lock :
synchronized void methodA() {
while (true) {
System.out.println("inside A , " + Thread.currentThread()
.getName());
try {
wait();
} catch (InterruptedException e) {
// handle it
}
}
}
prints :
inside A , t1
inside A , t2
Use notify() (to notify a waiting thread) and wait() (to make the current thread wait and release the lock if it has) to make threads collaborating between them :
synchronized void methodA() {
while (true) {
notify();
System.out.println("inside A , " + Thread.currentThread()
.getName());
try {
wait();
} catch (InterruptedException e) {
// handle it
}
}
}
prints :
inside A , t1
inside A , t2
inside A , t1
inside A , t2
...
That is intended situation.
Your t1 thread is waiting in another thread not main thread.
In your main thread(make threads and call start()), just waiting 5 seconds and start thread2
your synchronized method is synchronizing only when thread 1 calls that method not forever.
After thread1 calls synchorinized method and return, thread1 is stopping 5seconds.
In that time, thread2 can use that method.
The keyword synchronized infront of a method means, that the method cannot be called by two threads at the same time.
As soon as the method is called by a thread, other threads trying to call that same method are blocked until the first thread returns from that method. Afterwards the other threads calling the same method can automatically continue with the call (one at a time).
You implicit lock with synchronized is working for a short period - that is the println after that the lock is released. Both of your threads are racing to obtain the lock there.
Change your code to this and you will see the behavior you want
class MyThread implements Runnable {
#Override
public void run() {
methodA();
}
}
synchronized void methodA() {
while(true)
System.out.println("inside A , " + Thread.currentThread().getName());
}
Related
I'm having a hard time understanding synchronized. Since the first thread doesn't do anything with the object 2, doesn't it "unlock" everything in a second?
public class Uninterruptible {
public static void main(String[] args) throws InterruptedException {
final Object o1 = new Object(); final Object o2 = new Object();
Thread t1 = new Thread() {
public void run() {
try {
synchronized(o1) {
Thread.sleep(1000);
synchronized(o2) {}
}
} catch(InterruptedException e) { System.out.println("t1 interrupted"); }
}
};
Thread t2 = new Thread() {
public void run() {
try {
synchronized(o2) {
Thread.sleep(1000);
synchronized(o1) {}
}
} catch(InterruptedException e) { System.out.println("t2 interrupted"); }
}
};
t1.start(); t2.start();
Thread.sleep(2000);
t1.interrupt(); t2.interrupt();
t1.join(); t2.join();
System.out.println("Donezo!");
}
}
It doesn't matter that the inner synchronized blocks do nothing. Java will still attempt to acquire the lock on the the object specified.
No matter whether you have nothing or a huge amount of processing in the inner synchronized blocks, what you have is the minimal example to create a deadlock: two different threads, each owning the lock on a distinct resource, each attempting to acquire the lock on each other's resource.
The deadlock occurs before either thread even gets to executing the inner synchronized block, because neither thread can get locks on both resources at the same time.
The code winds up doing nothing but hanging, with each thread blocked. Your calls to interrupt are too late to cause an InterruptedException; they only set the "interrupted status" in the Thread. Commenting out Thread.sleep(2000) will let the calls to interrupt catch the Threads while they are still sleeping, before they even attempt to acquire the second lock.
This program works fine by printing alternate numbers via different threads but when all the numbers from 0-9 are printed Why does this program not stop? I have to manually stop my application.
public class EvenOddPrinter implements Runnable{
private AtomicInteger num = new AtomicInteger(0);
private Object lock = new Object();
#Override
public void run() {
synchronized (lock){
while (num.get()<10){
System.out.println(num.getAndAdd(1) + " - "+Thread.currentThread().getName());
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Executor {
public static void main(String[] args) throws InterruptedException {
EvenOddPrinter eop = new EvenOddPrinter();
Thread t1 = new Thread(eop);
Thread t2 = new Thread(eop);
t1.start();
t2.start();
}
}
that's because in the last Thread getting stuck at wait. notifyAll will notify all waiting thread if any there and release lock.
while (num.get()<10){
// existing implementation
}
lock.notifyAll();
The second thread t2 keeps waiting on the lock in the end, and t1 doesnt do the notify() anymore because the while condition becomes false. You must put a lock.notify(); statement outside of the while loop.
As soon as the number reached 8 the first thread calls notify() and goes to wait(). Second thread then makes the number 9 and calls notify() and goes to wait(). First thread is then not able to go inside the loop as specified in the condition, therefore, it exits the synchronized and block and finishes but second thread is still waiting. There has to be a mechanism to notifyAll() as soon as one of the threads exits the synchronized block which is exactly what I did.
#Override
public void run() {
synchronized (lock){
while (num.get()<10){
System.out.println(num.getAndAdd(1) + " - "+Thread.currentThread().getName());
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notifyAll();
}
Also, lock is pointless when I am using AtomicInteger (or the other way round).
I have two threads t0 and t1 with runnables posted below in the code section Run_0 and Run1 respectively. what I want to do is, when t0 is writing or doing its task that lasts for 7 seconds, t1 should be waiting. and when the
7 seconds elapse, t1 should be notified to continue working. I tried to do that using wait() and notify() but at run time i expected t0 to start but the console displays only "T1 is working" and t0 prints nothing as if it was not
started
please let me know why such behaviour is happening.
code:
public static void main(String[] args) {
t0 = new Thread(new Run_0());
t1 = new Thread(new Run_1());
t0.start();
t1.start();
}
private static class Run_0 implements Runnable {
public void run() {
// TODO Auto-generated method stub
while (true) {
long startTime = TimeUtils.getTSSec();
synchronized (t1) {
try {
t1.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("T0 is writing");
//simulate doing some work
while( (TimeUtils.getTSSec()-startTime) <= 7) {
}
System.out.println("T0 finished writing");
synchronized (t1) {
t1.notify();
}
startTime = TimeUtils.getTSSec();
while( (TimeUtils.getTSSec()-startTime) <= 7) {
}
}
}
}
private static class Run_1 implements Runnable {
public void run() {
// TODO Auto-generated method stub
while(true) {
System.out.println("T1 is working");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
From the javadocs (emphasis mine):
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.
Your code causes t0 to wait, not t1.
wait, notify and notifyAll should be inside synchronized block. You have one notify that is outside it:
t1.notify(); // <-------
startTime = TimeUtils.getTSSec();
the console displays only "T1 is working" and t0 prints nothing as if it was not started
Right because the first thing in Run_0.run() is t1.wait();. That is waiting for someone to call t1.notify() or t1.notifyAll(). I see no one calling those.
When a thread calls wait() on an object, it causes the thread to wait for the monitor on the object to be notified. One thread doesn't cause another thread to wait. It can only wait itself.
It is important to realize that you are synchronizing, waiting, and notifying on the t1 object which happens to be a thread. Any object shared between the two threads will work and since we are getting confused with locking on the t0 or t1 thread object, you should instead create a final lock object and lock on it:
private final Object lock = new Object();
t0 is writing or doing its task that lasts for 7 seconds, t1 should be waiting.
So it sounds like you should have the t1.wait() in the Run_1 class not the Run_0 class. Maybe Run_0 should do:
// much better way to simulate time passing instead of a spin loop
Thread.sleep(7000);
System.out.println("T0 finished writing");
synchronized (lock) {
lock.notify();
}
and then in Run_1 you'd do something like:
synchronized (lock) {
lock.wait();
}
System.out.println("T1 is working");
Notice that I'm using the common lock object.
I was trying to create A Java dead lock program . I know in real time we wont be creating any dead lock in thread. Unfortunately I have been asked in one of the interview to writing a "Deadlock program using two threads". So here it is
package Thread.DeadLock;
public class deadLock2 {
static ThreadSample1 t1 = new ThreadSample1();
static ThreadSample2 t2 = new ThreadSample2();
public static void main(String args[]) {
t1.start();
t2.start();
}
public static class ThreadSample1 extends Thread {
public void run() {
System.out.println("In first run method");
try {
System.out.println("Holding lock in first one");
synchronized (t1) {
System.out.println("t1 going to wait for t2");
t1.wait();
System.out.println("t1 finished for waiting");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static class ThreadSample2 extends Thread {
public void run() {
System.out.println("In second run method");
try {
System.out.println("Holding lock for second one");
synchronized (t2) {
System.out.println("t2 going to wait for t1");
t2.wait();
System.out.println("t2 finished for waiting");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
I can see the program is getting stuck. I am assuming that it in deadlock situation. t1.start() waits for t2 to finish its task and t2.start() waits for t1 to finish its task. Now while I try to remove the deadlock by notifying the waiting thread using using t1.notify() I get IllegalMonitorStateException.
Can somebody tell in this situation how to remove the deadlock without causing any situation.
First, this is not deadlock. As you correctly described, deadlock is usually situation when there is circular dependency between two or more threads waiting for resources that is held by other thread.
Here, each thread independently waits for notification on itself which is actually not delivered by anybody else in the system. Even if there is no deadlock.
Secondly, IllegalMonitorStateException means that you try to notify/wait on monitor which is not held by the thread. In other words, there is no synchronized prior to notify/wait.
Third, to achieve real deadlock you can do something like this:
synchronized(t1) {
synchronized(t2) {
t2.wait();
}
t1.notify();
}
and vice versa for the other thread.
You can not call notify()/notifyAll() unless the current thread owns that object's monitor. To do that, you must synchronize on it, as you did with wait()
The Javadocs for wait() mention this:
This method should only be called by a thread that is the owner of this object's monitor. See the notify method for a description of the ways in which a thread can become the owner of a monitor.
Throws:
IllegalMonitorStateException – if the current thread is not the owner of this object's monitor.
And from notify():
A thread becomes the owner of the object's monitor in one of three
ways:
By executing a synchronized instance method of that object.
By executing the body of a synchronized statement that synchronizes on the object.
For objects of type Class, by executing a synchronized static method of that class.
See this answer:
Java Wait and Notify: IllegalMonitorStateException
package pck.pramod.geekforgeeks;
public class ThreadDeadlock {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String args[]) {
System.out.println(Lock1.toString() + " " + Lock2.toString());
ThreadDemo1 T1 = new ThreadDemo1(Lock1, Lock2, "T1");
ThreadDemo1 T2 = new ThreadDemo1(Lock2, Lock1, "T2");
T1.start();
T2.start();
}
}
class ThreadDemo1 extends Thread {
Object lock1;
Object lock2;
String name;
public ThreadDemo1(Object lock1, Object lock2, String name) {
this.lock1 = lock1;
this.lock2 = lock2;
this.name = name;
}
public void run() {
synchronized (lock1) {
System.out.println(name + " Holding lock ..." + lock1.toString());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
System.out.println(name + " Waiting for lock ..." + lock2.toString());
synchronized (lock2) {
System.out.println(name + " Holding lock ..." + lock1.toString() + " " + lock2.toString());
}
}
}
}
Am I not using synchronization properly:
In following code i am having 2 problems :
1. while makingmethods (designBusiness,createBusiness,sellBusiness) as synchronized like in this case, a call to wait() says IllegalMonitorStateException but i can not understand why? because in designBusiness method Designer Thread do get a lock so it is supposed to wait on wait call. I am getting IllegalMonitorStateException on wait() and notify() both.
2.Even though when i remove synchronized keyword and use synchronized(this) block for particularly wait() and notify() still i got DEADLOCK! WHY?
public class Main {
HashMap<String, Integer> map = new shop().orderBook();
public static void main(String[] args) throws InterruptedException {
Main main = new Main();
main.sellBusiness();
Thread.sleep(3000);
main.designBusiness();
Thread.sleep(3000);
main.createBusiness();
}
private synchronized void designBusiness() throws InterruptedException {
Thread designThread = new Thread(new Runnable() {
public void run() {
Set set = map.keySet();
System.out.println("Tracking OrderList");
System.out.println(set.size());
try {
System.out.println("waiting.........");
wait();
System.out.println("wait completed");
System.out.println("after design process items in orderList are "
+ map.keySet().size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Designer Thread");
designThread.start();
System.out
.println("status of Designer Thread" + designThread.isAlive());
}
private synchronized void createBusiness() throws InterruptedException {
Thread createThread = new Thread(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName()
+ " started");
Creator creator = new Creator();
creator.create(map);
notifyAll();
System.out.println("notified");
}
}, "Creator Thread");
createThread.start();
createThread.join();
System.out.println("status of Creator Thread" + createThread.isAlive());
}
private void sellBusiness() throws InterruptedException {
Thread sellThread = new Thread(new Runnable() {
public void run() {
Seller seller = new Seller();
seller.sellGold(45000, 15);
seller.sellSilver(14000, 60);
seller.noteOrder("Mrs Johnson", 15000, map);
seller.noteOrder("Mr. Sharma", 10000, map);
seller.sellGold(60000, 20);
seller.noteOrder("Mr. Hooda", 17500, map);
System.out.println(Thread.currentThread().getName()
+ " done selling");
}
}, "Seller Thread");
sellThread.start();
sellThread.join();
System.out.println("status of seller Thread" + sellThread.isAlive());
}
}
please help i could not find any solution for this problem and i am searching from last night.
If you got this exception you are not in a block or method that is synchronised on the object you are waiting on. That is the meaning of the exception. The only meaning.
The wait() method you are calling is executed on the instance of the anonymous inner class you are creating. The synchronised method you are creating it from is synchronised on a different object, and it has probably also already executed by the time the inner object gets to the wait() call.
You need to sort out which object is which here. Probably you need to call Main.this.wait(), but it depends on what you think you're trying to do, which isn't clear from your question.
NB you aren't getting a deadlock, you are getting an infinite block. It isn't the same thing.
wait(), notify() and notifyAll() must be used with synchronized. What I would do is trying to solve the deadlock.
To illustrate why you got deadlock (unrelated code removed) (if I guessed right):
public class Main {
public static void main(String[] args) throws InterruptedException {
Main main = new Main();
main.createBusiness();
}
private synchronized void createBusiness() throws InterruptedException {
// ^^^^^^^^^^^^ got lock
Thread createThread = new Thread(new Runnable() {
public void run() {
synchronized (Main.this) {
// ^^^^^^^^^^^^^^^^^^^^^^^^ try to get lock --> DEADLOCK
Main.this.notifyAll();
}
}
});
createThread.start();
createThread.join();
// ^^^^^^^^^^^^^^^^^^^ wait for createThread to die --> DEADLOCK
}
}
Main thread got the lock of Main.this.
createThread tried to get lock of Main.this, but it's locked by Main.this, hence waiting.
Main thread waited for createThread to die, hence waiting. (2 and 3 can be swapped)
Since I'm not sure what you tried to achieve, I'm not sure if the following is the right solution, but you can try (even if the above guessed wrong):
First, create a lock object.
public class Test {
private Object lock = new Object();
Second, in designer thread
synchronized (lock) {
lock.wait();
}
Third, in creator thread
synchronized (lock) {
lock.notifyAll();
}
wait() must be executed from synchronized block on the same monitor. Since wait() is the same as this.wait() you have to wrap it with synchronized(this):
synchronized(this) {
wait();
}
If you try to unlock an onject by a threas which is not locked by that thread then you may end up with the same error.