can not reproduce deadlock using the next code
I am trying yo get a deadlock using the next code,
but it seems that it works good.
Please see below:
public class Deadlock {
static Object lock1 = new Object();
static Object lock2 = new Object();
public static void main(String[] args) {
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
synchronized (lock1) {
System.out.println("Thread 1: locked lock1");
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("Thread 1: locked lock2");
}
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
synchronized (lock2) {
System.out.println("Thread 2: locked lock2");
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock1) {
System.out.println("Thread 2: locked lock1");
}
}
}
}).start();
}
}
What I don't understand in this case or what's wrong in this code?
To cause a deadlock, you need to hold both locks in these threads in reverse order.
// thread 1
public void run() {
synchronized (lock1) {
synchronized (lock2) {
// do something
}
}
}
// thread 2
public void run() {
synchronized (lock2) {
synchronized (lock1) {
// do something
}
}
}
This is necessary, but not sufficient. To be able to simulate the deadlock, you need to make sure both threads acquire their first locks respectively successfully before attempting to acquire the next.
Why would the above code cause a deadlock? Each thread only locks one lock at a time, so if the other thread tries to lock it, it just has to wait for the first one to release it.
You would have a serious risk of deadlock if the threads did
synchronized (lock1) {
synchronized (lock2) {
...
}
}
and
synchronized (lock2) {
synchronized (lock1) {
...
}
}
Your code will never "dead lock".
To dead lock, you must lock the other lock within a lock.
To get a deadlock you need to hold two locks at once. You can hold the first lock for the whole loop.
If you are trying to get a deadlock, you need to nest the synchronized blocks so that you attempt to whole both locks simultaneously:
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
synchronized (lock1) {
System.out.println("Thread 1: locked lock1");
try {
// Sleep to allow Thread2 to obtain lock2
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("Thread 1: locked lock2");
}
}
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
// Sleep to allow Thread1 to obtain lock1
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("Thread 2: locked lock2");
synchronized (lock1) {
System.out.println("Thread 2: locked lock1");
}
}
}
}
}).start();
Note that the locks are acquired in reverse order, with sleeps to ensure the following acquisition order:
Thread 1 acquires lock1
Thread 2 acquires lock2
Thread 1 attempts to acquire lock2 <--- DEADLOCK
Thread 2 attempts to acquire lock1 <--- DEADLOCK
Note that the last two can happen in either order, but the deadlock will occur regardless.
Have the second thread try to get a lock on lock1. That's the classic way to invoke deadlock. Two resources locked in different orders.
Sorry... didn't scroll down far enough in your code... feeling foolish
Related
I want to use 3 threads to print A、B、C randomly,so I wrote code as below:
public class ThreadPrint4Test {
public static void main(String[] args) {
new ThreadPrint4Test().testPrint();
}
public void testPrint() {
Object lock = new Object();
new Thread(new PrintThread("A",lock),"thread-A").start();
new Thread(new PrintThread("B",lock),"thread-B").start();
new Thread(new PrintThread("C",lock),"thread-C").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
new Thread(() -> {
synchronized (lock) {
lock.notifyAll();
}
}).start();
}
class PrintThread implements Runnable {
private Object lock;
private String value;
public PrintThread(String value, Object lock) {
this.value = value;
this.lock = lock;
}
public void run() {
while (true) {
try {
synchronized (lock) {
lock.wait();
System.out.println(LocalTime.now() + "\t" + value);
lock.notifyAll();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
But when I test the program,it stoppted print characters after a few seconds
Using jps and jstack I found all the 3 threads are WAITING the object lock
I tested it for serveral times,and this phenomenon occurs every time.
I do not know why all the 3 threads are waiting object lock at same time
Based on my knowledge,each time one of the 3 threads will be awake and have the chance to exeute,then it will awake all the 3 threads randomly by invoking lock.notifyAll();. So the program should run continuous theoretically,But now each time I test it,it will stop print characters after a few seconds.
Could someone help analysis why this happen? Thanks in advance!
while (true) {
try {
synchronized (lock) {
lock.wait();
System.out.println(LocalTime.now() + "\t" + value);
lock.notifyAll();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
Your problem is that you are calling notifyAll() immediately after calling wait(). You get to a deadlock situation where each thread is waiting. When all the threads are waiting, none of them can be notified, hence your program comes to a standstill.
According to the Concurrency tutorial, you need to wait() for a certain condition to occur. Once the condition occurs, you perform the required action (which, in your code, is printing the current time) then you call notifyAll() to inform the waiting threads that you have completed performing the required action and that they can try to perform their required action.
Explanations after the code.
import java.time.LocalTime;
public class ThreadPrint4Test {
private volatile boolean canPrint;
public void testPrint() {
Object lock = new Object();
new Thread(new PrintThread("A", lock), "thread-A").start();
new Thread(new PrintThread("B", lock), "thread-B").start();
new Thread(new PrintThread("C", lock), "thread-C").start();
}
class PrintThread implements Runnable {
private Object lock;
private String value;
public PrintThread(String value, Object lock) {
this.value = value;
this.lock = lock;
canPrint = true;
}
public void run() {
while (true) {
while (!canPrint) {
try {
synchronized (lock) {
System.out.printf("[%s] Waiting...%n", value);
lock.wait();
}
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
synchronized (lock) {
canPrint = false;
System.out.println(LocalTime.now() + "\t" + value);
canPrint = true;
lock.notifyAll();
}
}
}
}
public static void main(String[] args) {
new ThreadPrint4Test().testPrint();
try {
Thread.sleep(2000);
}
catch (InterruptedException x) {
x.printStackTrace();
}
System.exit(0);
}
}
I added a canPrint flag. When it is true, then the thread can print the current time. When it is false, the thread must wait.
When the thread can print the current time, it first sets the flag to false so that no other thread can print.
After the thread has printed the current time, it sets the flag back to true and calls method notifyAll() which causes all waiting threads to stop waiting and re-check the canPrint flag.
The first thread to awake after canPrint has been set to true, sets the flag to false which causes all other threads to wait.
This question already has answers here:
Java: Are all monitors released when thread waits on an object?
(3 answers)
Closed 8 years ago.
Will this work or result in deadlock?
thread 1:
synchronized (globalLock) {
synchronized (o) {
o.wait();
}
}
thread 2 (later):
synchronized (globalLock) {
synchronized (o) {
o.notify();
}
}
So from what I understand, o.wait() will release the lock of o, but will it release the lock of globalLock? Probably not and this will result in deadlock?
As mentioned in comments, this is trivially easy to test. Yes, it does deadlock for the reasons you guessed.
public static void main(String[] args) throws InterruptedException {
final Object globalLock = new Object();
final Object o = new Object();
new Thread(new Runnable() {
#Override
public void run() {
synchronized (globalLock) {
synchronized (o) {
try {
System.out.println("waiting");
o.wait();
} catch (InterruptedException ie) {
// no-op
}
}
}
}
}).start();
Thread.sleep(2000); // ensure thread above starts first
new Thread(new Runnable() {
#Override
public void run() {
synchronized (globalLock) {
synchronized (o) {
System.out.println("notifying");
o.notify();
}
}
}
}).start();
}
Yes deadlock when Thread 1 started before Thread2.
Thread 2 will never be able to execute its :
synchronized (globalLock)
because Thread 1 has never come out of synchronized (globalLock)
I am trying to use 2 threads. 1 thread prints only odd number and the other thread prints only even number and It has to be an alternative operation.
Eg:
Thread1 1
Thread2 2
Thread1 3
Thread2 4
and so on..
Below is the program, please let me know where I am going wrong as the thread1 is not coming out of wait state even when the thread2 is notifying it..
public class ThreadInteraction {
public static void main(String[] args) {
new ThreadInteraction().test();
}
private void test() {
ThreadA ta = new ThreadA();
Thread t = new Thread(ta);
t.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
for(int i=2;i<=50;){
System.out.println("Thread2 "+i);
synchronized (t) {
try {
t.notify();
t.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
i=i+2;
}
}
}
class ThreadA implements Runnable{
#Override
public void run() {
for(int i=1;i<50;){
System.out.println("Thread1 "+i);
synchronized (this) {
try {
notify();
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i=i+2;
}
}
}
Problem is that in one case you are taking lock on Thread t [synchronized (t) ] while in other case you are taking lock on TheadA object itself [synchronized(this)].
If you want threads to talk to each other then both should take lock on same object only then wait notify will work as you expect.
Edit:
There is another problem in your program, you are not using any variable to coordinate between 2 threads. SO you may see output like this 2,1,4,3...so on. Point is threads will work alternately but not in sequence.
So you should share a single variable between 2 threads which should be incremented.
Second issue is you are not taking care of spurious wake up calls [read some docs on this], you should always have wait called inside a while loop.
Modified my code based on the answer provided by Lokesh
public class ThreadInteraction {
public static void main(String[] args) {
new ThreadInteraction().test();
}
private void test() {
ThreadA ta = new ThreadA();
Thread t = new Thread(ta);
t.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
for(int i=2;i<=50;){
System.out.println("Thread2 "+i);
synchronized (ta) {
try {
ta.notify();
ta.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
i=i+2;
}
}
}
class ThreadA implements Runnable{
#Override
public void run() {
for(int i=1;i<50;){
System.out.println("Thread1 "+i);
synchronized (this) {
try {
notify();
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i=i+2;
}
}
}
You have a real confusion of threads and locks. I suggest you create one and only one object to use for locking to start with as you don't appear to have a clear idea what you are locking.
If you notify() and nothing is listening, the signal is lost. However, a wait() can wake spuriously.
For this reason, a notify() should be accompanied by a state change and a wait() should be in a loop checking that change.
I'm trying to check how wait/notify works in java.
Code:
public class Tester {
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
synchronized (t) {
try {
System.out.println("wating for t to complete");
t.wait();
System.out.println("wait over");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyRunnable implements Runnable {
public void run() {
System.out.println("entering run method");
synchronized (this) {
System.out.println("entering syncronised block");
notify();
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("leaving syncronized block");
}
System.out.println("leaving run method");
}
}
Output Returned
wating for t to complete
entering run method
entering syncronised block
//sleep called
leaving syncronized block
leaving run method
wait over
I was expecting when notify() is executed the wait will be over & System.out.println("wait over"); will get printed. But it seems it only gets printed when t finished its run().
Object monitor locks need to be performed a single reference of the same lock...
In your example you are waiting on an instance of the Thread, but using notify from the Runnable. Instead, you should use a single, common lock object...for example
public class Tester {
public static final Object LOCK = new Object();
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread t = new Thread(r);
t.start();
synchronized (LOCK) {
try {
System.out.println("wating for t to complete");
LOCK.wait();
System.out.println("wait over");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static class MyRunnable implements Runnable {
public void run() {
System.out.println("entering run method");
synchronized (LOCK) {
System.out.println("entering syncronised block");
LOCK.notify();
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("leaving syncronized block");
}
System.out.println("leaving run method");
}
}
}
Output...
wating for t to complete
entering run method
entering syncronised block
leaving syncronized block
wait over
leaving run method
wait over and leaving run method could change positions depending on the thread scheduling.
You could try putting the sleep out side the synchronized block. This will release the monitor lock allowing the wait section to continue running (as it can't start until the lock is released)
public static class MyRunnable implements Runnable {
public void run() {
System.out.println("entering run method");
synchronized (LOCK) {
System.out.println("entering syncronised block");
LOCK.notify();
System.out.println("leaving syncronized block");
}
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("leaving run method");
}
}
Answer to updated code :
From Thread.sleep() javadoc:
Causes the currently executing thread to sleep (temporarily cease execution) for the
specified number of milliseconds, subject to the precision and accuracy of system timers
and schedulers. The thread does not lose ownership of any monitors.
If you call Thread.sleep while inside a synchronized block, other threads won't be able to enter the synchronized block. You should never do time consuming tasks while in a synchronized block to avoid this.
Note (as others pointed out as well) that you have to use the same object for locking/synchronizing in both threads.
If you want your main thread to continue immediately after notify is called, you have to relinquish the lock temporarily. Otherwise wait will get called only after the secondary thread leaves the synchronized block. And it's never a good idea to keep a lock in a long running computation!
One way how to achieve is to use wait(int) on the lock instead of sleep, because wait releases the synchronization lock temporarily:
public class Tester {
private static final Object lock = new Object();
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
synchronized (lock) {
try {
System.out.println("wating for t to complete");
lock.wait();
System.out.println("wait over");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class MyRunnable implements Runnable {
public void run() {
System.out.println("entering run method");
synchronized (lock) {
System.out.println("entering syncronised block");
lock.notify();
try {
lock.wait(1000); // relinquish the lock temporarily
} catch (InterruptedException ex) {
System.out.println("got interrupted");
}
System.out.println("leaving syncronized block");
}
System.out.println("leaving run method");
}
}
}
However, using these low-level primitives can be very error prone and I'd discourage from using them. Instead, I'd suggest you to use Java's high-level primitives for that. For example, you can use CountDownLatch which lets one thread wait until other threads count down to zero:
import java.util.concurrent.*;
public class TesterC {
private static final CountDownLatch latch = new CountDownLatch(1);
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
System.out.println("wating for t to complete");
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("wait over");
}
static class MyRunnable implements Runnable {
public void run() {
System.out.println("entering run method");
try {
latch.countDown();
Thread.sleep(1000);
} catch (InterruptedException ex) {
System.out.println("got interrupted");
}
System.out.println("leaving run method");
}
}
}
Here you don't have to synchronize anything, the latch does everything for you. There are many other primitives you can use - semaphores, an exchanger, thread-safe queues, etc. Explorer the java.util.concurrent package.
Perhaps even better solution is to use even higher level API, such as Akka provides. There you work with Actors or Software transactional memory, which can be composed easily and spare you of most of concurrency issues.
How can two threads access a synchronized block simultaneously? That is, how can I make one thread give the chance for the other thread to execute a synchronized block, even before this thread finishes the execution of the same synchronized block?
See wait(), notify(), and notifyAll().
Edit: The edit to your question is incorrect. The sleep() method does not release the monitor.
For example:
private static final Object lock = new Object();
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(new One());
executorService.execute(new Two());
}
static class One implements Runnable {
#Override
public void run() {
synchronized (lock) {
System.out.println("(One) I own the lock");
System.out.println("(One) Giving up the lock and waiting");
try {
lock.wait();
} catch (InterruptedException e) {
System.err.println("(One) I shouldn't have been interrupted");
}
System.out.println("(One) I have the lock back now");
}
}
}
static class Two implements Runnable {
#Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.err.println("(Two) I shouldn't have been interrupted");
}
synchronized (lock) {
System.out.println("(Two) Now I own the lock (Two)");
System.out.println("(Two) Giving up the lock using notify()");
lock.notify();
}
}
}
It sounds like you might want to consider using more than one synchronized block, particularly if there's a blocking operation that one thread is getting caught on and thus blocking another thread that wants to execute something else in the block.
A synchronized block is a block of code which can (by definition) only be accessed by one thread at a time.
Saying that you want another thread to enter this block while another thread also currently processes it, does make the synchronized block scheme useless.
You probably want to split the synchronized block into many other ones.
The only way I can see if one thread calls wait() on monitor object. Then it will release monitor and wait for notification while other thread can execute synchronized block. Then other thread will have to call notify()/notifyAll() so first thread gets monitor back and continue.
A thread can release its monitor using lock.wait(). Another thread can then pick up the monitor and enter the synchronized block.
Example:
public class MultipleThreadsInSynchronizedBlock {
public static void main(String... args) {
final Object lock = new Object();
Runnable runnable = new Runnable() {
public void run() {
synchronized (lock) {
System.out.println("Before wait");
try {
lock.wait();
} catch (InterruptedException e) {
}
System.out.println("After wait");
}
}
};
new Thread(runnable).start();
new Thread(runnable).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
synchronized (lock) {
lock.notifyAll();
}
}
}
This prints:
Before wait
Before wait
After wait
After wait
However it's not a "hack" to allow a mutually exclusive block to be run non-atomically. If you're going to use very low-level synchronization primitives like this you need to know what you're doing.