I visited interview some recently. Interviewer asked me to write guaranteed deadlock.
I have wrote following:
public class DeadLockThreadSleep {
private static class MyThread implements Runnable {
private Object o1;
private Object o2;
#Override
public void run() {
try {
test(o1, o2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public MyThread(Object o1, Object o2) {
this.o1 = o1;
this.o2 = o2;
}
public void test(Object o1, Object o2) throws InterruptedException {
synchronized (o1) {
System.out.println("1.acquired: " + o1);
Thread.sleep(1000);
synchronized (o2) {
System.out.println("2.acquired: " + o2);
}
}
}
}
public static void main(String[] args) {
Object o1 = new Object();
Object o2 = new Object();
new Thread(new MyThread(o1, o2)).start();
new Thread(new MyThread(o2, o1)).start();
}
}
Then he asked if I sure that it is guaranted. I rememebered that Thread.sleep nothing guaranteed.
Then I wrote this code:
public static void main(String[] args) {
final Thread mainThread = Thread.currentThread();
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
mainThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this answer was accepted.
Also he asked to write analog via wait/notify. I thought a lot and I cannot imagine how to write this.
Is it possible?
This may be done by creating a cycle where one thread holds a resource and waits for another resource whereas the other thread does the same but in reverse order.
Thread tholds resourceOne and waits for resourceTwo , whereas t1holds resourceTwo and waits for resourceOne
Below is a sample code:
public class WaitNotifyLock {
boolean isONHold = false;
public synchronized void hold(){
while(isONHold){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
isONHold = true;
System.out.println(Thread.currentThread().getId() + " : Holded");
}
public synchronized void unHold(){
while(!isONHold){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getId() + " : Produced");
isONHold = false;
notify();
}
public static void main(String[] args) {
WaitNotifyLock resourceOne = new WaitNotifyLock();
WaitNotifyLock resourceTwo = new WaitNotifyLock();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
resourceOne.hold();
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
resourceTwo.hold();
resourceOne.unHold();
resourceTwo.unHold();
}
});
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
resourceTwo.hold();
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
resourceOne.hold();
resourceTwo.unHold();
resourceOne.unHold();
}
});
t.start();
t1.start();
}
}
A deadlock is a so-called liveness hazard (others are starvation, poor responsiveness, or livelocks), where two main types can be considered:
Lock-ordering deadlocks
Resource deadlocks
However, the Java documentation simplifies this as follows:
Deadlock describes a situation where two or more threads are blocked forever, waiting for each other.
Hence, IMHO you could simply enforce a deadlock with this:
public class DeadlockDemo {
public static void main(String[] args) {
Object a = new Object();
Object b = new Object();
new Thread(() -> waitLeftNotifyRight(a, b)).start();
waitLeftNotifyRight(b, a);
}
public static void waitLeftNotifyRight(Object left, Object right) {
synchronized (left) {
try {
System.out.println("Wait");
left.wait();
} catch (InterruptedException e) { /* NOP */ }
}
synchronized (right) {
System.out.println("Notify");
right.notify();
}
}
}
This demo never terminates because the created thread waits on a's monitor, whereas the main thread waits on b's monitor. As a result, the corresponding notify() methods aren't invoked (which would terminate the program).
Related
I write a Java program to solve Producer Consumer problem in Multi-Threads. But it can not work correctly.
The program:
public class ConsumerAndProducer {
static int products = 0;
static int capacity = 10;
public static void main(String[] args) {
new Thread(new Producer()).start();
new Thread(new Consumer()).start();
}
static class Consumer implements Runnable{
public void consume() {
synchronized (ConsumerAndProducer.class){
if(products <= 0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
products--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consumer, remain:" + products);
if(products == 9){
notify();
}
}
}
#Override
public void run() {
while(true){
consume();
}
}
}
static class Producer implements Runnable{
public void produce() {
synchronized (ConsumerAndProducer.class){
if(products == capacity){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
products++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Producer, remain:" + products);
if(products == 1){
notify();
}
}
}
#Override
public void run() {
while(true){
produce();
}
}
}
And the errors:
Producer, remain:1
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at zhousai.ConsumerAndProducer$Producer.produce(ConsumerAndProducer.java:69)
at zhousai.ConsumerAndProducer$Producer.run(ConsumerAndProducer.java:77)
at java.lang.Thread.run(Thread.java:748)
Consumer, remain:0
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at zhousai.ConsumerAndProducer$Consumer.consume(ConsumerAndProducer.java:22)
at zhousai.ConsumerAndProducer$Consumer.run(ConsumerAndProducer.java:43)
at java.lang.Thread.run(Thread.java:748)
When I ran your code, I got the following error:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException: current thread is not owner
The line of your code throwing that exception is the call to method wait().
You are calling method wait() of class Producer but you are synchronizing on ConsumerAndProducer.class. The wait() method must be called on the object that you are synchronizing on, because that object owns the lock and you must call wait() on the object that owns the lock. Hence the error message: current thread not owner.
The simplest solution is to change your code such that you call ConsumerAndProducer.class.wait() rather than just wait().
Here is your code with my suggested fix:
public class ConsumerAndProducer {
static int products = 0;
static int capacity = 10;
public static void main(String[] args) {
new Thread(new Producer()).start();
new Thread(new Consumer()).start();
}
static class Consumer implements Runnable {
public void consume() {
synchronized (ConsumerAndProducer.class){
if (products <= 0) {
try {
ConsumerAndProducer.class.wait(); // change here
} catch (InterruptedException e) {
e.printStackTrace();
}
}
products--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Consumer, remain:" + products);
if(products == 9){
ConsumerAndProducer.class.notify(); // change here
}
}
}
#Override
public void run() {
while(true){
consume();
}
}
}
static class Producer implements Runnable{
public void produce() {
synchronized (ConsumerAndProducer.class){
if (products == capacity) {
try {
ConsumerAndProducer.class.wait(); // change here
} catch (InterruptedException e) {
e.printStackTrace();
}
}
products++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Producer, remain:" + products);
if(products == 1){
ConsumerAndProducer.class.notify(); // change here
}
}
}
#Override
public void run() {
while(true){
produce();
}
}
}
}
I am learning multithreading.
I tried to implement producer consumer problem in Java.Its working fine.
But if i remove notify call the program goes into a deadlock state.Why?
Its going on deadlock when size of queue becomes 0.Ideally when size becomes 0,wait should be called inside consumer and producer should started working.
import java.io.*;
import java.util.*;
class Consumer implements Runnable{
Queue<Integer> q;
int n;
public void run() {
while(true){
synchronized (q) {
while(q.size()==0){
try {
System.out.println("q.size="+q.size());
q.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("item consumed="+q.poll());
q.notify();
try {
Thread.sleep((int)(Math.random() * 100));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Consumer(Queue<Integer> queue,int n){
q=queue;
this.n=n;
}
}
class Producer implements Runnable{
Queue<Integer> q;
int n;
public void run() {
int x=1;
while(true){
synchronized (q) {
while(q.size()==n){
try {
q.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("item produced="+x+" q.size="+q.size());
q.add(x++);
q.notify();
try {
Thread.sleep((int)(Math.random() * 100));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Producer(Queue<Integer> queue,int n){
q=queue;
this.n=n;
}
}
public class App
{
public static void main( String[] args ) throws InterruptedException
{
int n=100;
Queue<Integer> q=new LinkedList<Integer>();
Thread t1=new Thread(new Producer(q, n));
Thread t2=new Thread(new Consumer(q, n));
t1.start();
t2.start();
t1.join();
t2.join();
}
}
you required notify because when one thread is on wait state because queue is empty or full come to running state if some other thread notify after putting if queue is empty and taking queue is full.
put q.wait(10); so your code will not go on deadlock because after time it will check while loop condition.
It is always best practice to use notify in above usecase
let's say i have 3 classes:
1. Storage which contains just one integer.
2. Counter which contains a thread inside who's responsible for counting (0,1,..,k) and stores each iteration of the loop index in Storage class.
3.Printer which contains a thread who's responsible for reading the value in class Storage and print it.
now i have to create a main class which creates these 3 objects runs the threads of Counter and Printer , and everynumber from(0,1,..,k) has to be printed just once and in the right order.
how do i synchronize the access to my Storage class so first i put a number inside Storage with Counter ,than print it with my Printer class ?
here's what i've wrote so far:
public class Storage {
private int num;
public Storage(){
}
public synchronized void setNum(int num){
this.num = num;
}
public synchronized int getNum(){
return num;
}
public class Counter implements Runnable {
Storage s;
public Counter(Storage t){
s = t;
}
#Override
public void run() {
int i = 0;
while(true){
s.setNum(i++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Printer implements Runnable {
Storage s;
public Printer(Storage s){
this.s= s;
}
#Override
public void run() {
while(true){
System.out.println(s.getNum());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public class mainProg {
public static void main(String[] args){
Storage s = new Storage();
Counter c = new Counter(s);
Printer p = new Printer(s);
Thread c1 = new Thread(c);
Thread p2 = new Thread(p);
c1.start();
p2.start();
}
}
EDIT: i found out a solution, here it is:
public class Storage {
private int num;
private boolean available = false;
public Storage(){
}
public synchronized void setNum(int num){
while(available){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
available = true;
notifyAll();
this.num = num;
}
public synchronized int getNum(){
while(!available){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
available = false;
notifyAll();
return num;
}
}
This approach won't work, because it's not guaranteed that for every cycle of Counter a cycle of Printer will be executed in a parallel thread. You need to be able to store more than a one value in your Storage.
You can use BlockingQueue here and rewrite your Storage class like this:
public class Storage {
private BlockingQueue<Integer> numbers = new LinkedBlockingQueue<Integer>();
public void setNum(int num) {
try {
this.numbers.put(num);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public int getNum() {
try {
return numbers.take();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
Note that if BlockingQueue is empty and Printer wants to get a new value, it will wait while a new element occurrs in the queue.
I try to understand java core synchronization.
I wrote code sample:
Program should write
left
right
10 times
package concurrency;
public class LeftRightWaitNotifyExample {
final static String str = "1";
public static void main(String[] args) {
new LeftLegThread(str).start();
new RightLegThread(str).start();
}
}
class LeftLegThread extends Thread {
String monitor;
public LeftLegThread(String str) {
monitor = str;
}
#Override
public void run() {
try {
makeStep();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void makeStep() throws InterruptedException {
synchronized (monitor) {
for (int i = 0; i < 10; i++) {
System.out.println("Left ");
wait();
}
}
}
}
class RightLegThread extends Thread {
String monitor;
public RightLegThread(String str) {
monitor = str;
}
#Override
public void run() {
try {
makeStep();
} catch (InterruptedException e) {
}
}
private void makeStep() throws InterruptedException {
synchronized (monitor) {
while (true) {
System.out.println("Right ");
notify();
wait();
}
}
}
}
I get this output:
Left
Right
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at concurrency.LeftLegThread.makeStep(LeftRightWaitNotifyExample.java:35)
at concurrency.LeftLegThread.run(LeftRightWaitNotifyExample.java:23)
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at concurrency.RightLegThread.makeStep(LeftRightWaitNotifyExample.java:61)
at concurrency.RightLegThread.run(LeftRightWaitNotifyExample.java:51)
Before I got this error when I used wait method non within synchronized block. But here I use wait within synchronized block
What is the cause of the problem and how to fix it?
update
I rewrite code according advice:
public class LeftRightWaitNotifyExample {
final static String str = "1";
public static void main(String[] args) throws InterruptedException {
new LeftLegThread(str).start();
Thread.sleep(100);
new RightLegThread(str).start();
}
}
class LeftLegThread extends Thread {
String monitor;
public LeftLegThread(String str) {
monitor = str;
}
#Override
public void run() {
try {
makeStep();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void makeStep() throws InterruptedException {
synchronized (monitor) {
for (int i = 0; i < 2; i++) {
System.out.println("Left ");
monitor.wait();
monitor.notify();
}
}
}
}
class RightLegThread extends Thread {
String monitor;
public RightLegThread(String str) {
monitor = str;
}
#Override
public void run() {
try {
makeStep();
} catch (InterruptedException e) {
}
}
private void makeStep() throws InterruptedException {
synchronized (monitor) {
while (true) {
System.out.println("Right ");
monitor.notify();
monitor.wait();
}
}
}
}
current output:
Left
Right
Left
Right
Right
Why does Right outs 3 but Left only twice. Why?
You are synchronizing on monitor, so you should wait() on monitor, too:
monitor.wait();
Right now you are waiting on this, which is not the owner of the monitor because synchronization is on monitor.
Note that of course the notify should also be done on the monitor object, and that you might want to consider using notify/notifyAll in both threads. Otherwise it may happen that one thread starves waiting for a missing notification. Using a timeout (the overloaded version of wait) might also be a good idea to catch corner cases.
The reason - The current thread is not the owner of the object's monitor.To call wait() method the current thread must own this object's monitor.
In your case you are obtaining monitor on monitor object instead current object(this object).
you are trying to lock monitor object.But it is locking thread object (LeftLegThread,RightLegThread).Actually it is not locked with synchronization.
monitor.wait(); will fix.
public class LeftRightWaitNotifyExample {
final static String str = "1";
public static void main(String[] args) throws InterruptedException {
new LeftLegThread(str).start();
Thread.sleep(1000);
new RightLegThread(str).start();
}
}
class LeftLegThread extends Thread {
String monitor;
public LeftLegThread(String str) {
monitor = str;
}
#Override
public void run() {
try {
makeStep();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void makeStep() throws InterruptedException {
synchronized (monitor) {
while (true) {
System.out.println("Left ");
monitor.wait();
monitor.notify();
Thread.sleep(1000);
}
}
}
}
class RightLegThread extends Thread {
String monitor;
public RightLegThread(String str) {
monitor = str;
}
#Override
public void run() {
try {
makeStep();
} catch (InterruptedException e) {
}
}
private void makeStep() throws InterruptedException {
synchronized (monitor) {
while (true) {
System.out.println("Right ");
monitor.notify();
monitor.wait();
Thread.sleep(1000);
}
}
}
}
So I have been working on a simple wait/notify example in Java and for some reason I have not been able to get it to run properly. If anyone is able to see what might be the issue It would be very appreciated!
public class ThreadDemonstration
{
private String str = null;
Thread stringCreator = new Thread(new Runnable()
{
public void run()
{
synchronized(this)
{
str = "I have text";
notify();
}
}
});
private Thread stringUser = new Thread(new Runnable()
{
public void run()
{
synchronized(this)
{
if(str == null)
{
try {
System.out.println("str is null, I need help from stringCreator");
wait();
System.out.println(str);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
});
public static void main (String [] args)
{
ThreadDemonstration td = new ThreadDemonstration();
td.stringUser.start();
td.stringCreator.start();
}
}
My current output is:
str is null, I need help from stringCreator
So for some reason the thread stringCreator does not wake up the stringUser or am I missing something else entirely?
Thank you!
Your blocks are synchronized over different objects. They should be synchronized over a common object, for example the monitor object below:
public class ThreadDemonstration
{
private String str = null;
private final Object monitor = new Object();
Thread stringCreator = new Thread(new Runnable()
{
public void run()
{
synchronized(monitor)
{
str = "I have text";
monitor.notify();
}
}
});
private Thread stringUser = new Thread(new Runnable()
{
public void run()
{
synchronized(monitor)
{
while(str == null) //changed from if to while. This allows you to wait again if the thread gets woken up by something other than the appropriate notify.
{
try {
System.out.println("str is null, I need help from stringCreator");
monitor.wait();
//removed print statement from here
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println(str); //added print statement here. str is guaranteed to not be null here.
}
}
});
In order to avoid creating a separate object for synchronization, you can use synchronized(ThreadDemonstration.this) or synchronized(ThreadDemonstration.class) for example.
Try this :
private Thread stringUser = new Thread(new Runnable() {
//-----
System.out.println("str is null, I need help from stringCreator");
notify();
wait(100);
System.out.println(str);
//----
});
You need to use the wait and notify of the same instance in order for it to work. Since you create two different objects (2 instances of Runnable) it will not work. I've written a simple example using two different classes using the main class' instance for the intrinsic lock. You could also us a 'dummy object' (Object lock = new Object) for this.
public class ThreadDemonstration {
private static String text;
public ThreadDemonstration(){
Thread user = new Thread(new StringUser(this));
Thread creator = new Thread(new StringCreator(this));
user.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
creator.start();
}
public class StringCreator implements Runnable{
private Object lock;
StringCreator(Object lock){
this.lock = lock;
}
#Override
public void run() {
synchronized(lock){
text = "Yeeeehaaaaa";
lock.notify();
}
}
}
public class StringUser implements Runnable{
private Object lock;
StringUser(Object lock){
this.lock = lock;
}
#Override
public void run() {
synchronized(lock){
if((text == null)){
System.out.println("I need help!");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(text);
}
}
}
public static void main(String[] args){
new ThreadDemonstration();
}
}