Confusion on Deadlock - java

public class SimpleDeadlock implements Runnable{
static SimpleDeadlock sc1=null;
static SimpleDeadlock sc2=null;
void access(SimpleDeadlock sc){
if(Thread.currentThread().getName().equals("Thread1"))
threadMethod1(sc);
if(Thread.currentThread().getName().equals("Thread2"))
threadMethod2(sc);
}
public synchronized void threadMethod1(SimpleDeadlock sc) {
System.out.println(Thread.currentThread().getName()+": threadMethod1");
try{
Thread.sleep(1000);
}
catch(InterruptedException ie){}
sc.deadlock();
}
public synchronized void threadMethod2(SimpleDeadlock sc) {
System.out.println(Thread.currentThread().getName()+": threadMethod2");
try{
Thread.sleep(1000);
}
catch(InterruptedException ie){}
sc.deadlock();
}
synchronized void deadlock() {
System.out.println("In deadlock...");
}
public void run(){
if(Thread.currentThread().getName().equals("Thread1"))
access(sc1);
if(Thread.currentThread().getName().equals("Thread2"))
access(sc2);
}
public static void main(String[] args) throws InterruptedException{
sc1=new SimpleDeadlock();
sc2=new SimpleDeadlock();
Thread thread1=new Thread(sc1);
Thread thread2=new Thread(sc2);
thread1.setName("Thread1");
thread2.setName("Thread2");
thread1.start();
thread2.start();
Thread.sleep(10000);
System.out.println(thread1.getName()+":"+thread1.getState());
System.out.println(thread2.getName()+":"+thread2.getState());
}
}
When I am interchanging the object in access method which is in run method this example occurs in deadlock as Thread1 waits for Thread2 to finish and vice versa.
But when it is in given state it doesn't go in deadlock. WHY? When thread1 calls synchronized method threadMethod1(), the object sc1 is locked. Then how in that method the locked object sc1 calls another synchronized method.

Locks in Java are reentrant. If a thread has already acquired a lock and tries to acquire it again, there won't be any problem.

Related

Proper use of wait and notify methods in Java threading

I am new to Java multithreading. I created simple producer-consumer pattern using wait and notify but my producer is getting called only once in tbe starting.
public class ThreadApp {
public static void main(String[] args) throws InterruptedException {
ProducerConsumerWorldp = new ProducerConsumerWorld();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
class ProducerConsumerWorld{
public void producer() throws InterruptedException{
synchronized (this) {
while(true){
System.out.println("Producer thread started running");
wait();
System.out.println("Resumed Producing");
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(true){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
notify();
Thread.sleep(2000);
System.out.println("consumed all");
}
}
}
}
I am creating separate threads for producer and consumer. Producer thread only gets called in the starting and then after it is never getting executed.
I tried two option to overcome this issue. first I put while condition outside of synchronized block second is given below.
class ProducerConsumerWorld{
public void producer() throws InterruptedException{
synchronized (this) {
while(true){
System.out.println("Producer thread started running");
notify();
wait();
System.out.println("Resumed Producing");
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(true){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
notify();
Thread.sleep(2000);
System.out.println("consumed all");
wait();
}
}
}
}
Both works great. Which one the of the appropriate solution to use ? I am still unable to figure out why the code I put in question is not working properly.
I am still unable to figure out why the code I put in question is not working properly
The wait() in producer() releases the monitor which allows consumer() to enter its synchronized block. Then the wait() in producer() starts waiting till consumer() calls notify() and releases the monitor (i.e. exits its synchronized block). You never exit synchronized in consumer() therefore the wait() in producer() is blocked forever
I am still unable to figure out why the code I put in question is not
working properly
I've managed to fix your code, and I've attached below the fixed code snippet.
I've introduced a boolean instance variable named isConsumed for the ProducerConsumerWorld. In doing so, what essentially happens is that after Producer Thread produces, he updates the state of isConsumed to false, since he has produced something which is yet to be consumed. Afterwards, the producer notifies the the Consumer thread, that Producer has finished producing. Next, it invokes wait() on the ProducerConsumerWorld which releases Producer's lock on ProducerConsumerWorld. Then, it waits for the lock on ProducerConsumerWorld.
Meanwhile, the Consumer Thead acquires the lock on ProducerConsumerWorld, which allows it to enter the consumer method, where it checks if there is produce yet to be consumed. If so, it consumes and updates the isConsumed variable to true, and notifies the produce has been consumed. Then the consumer proceeds to releases its lock on ProducerConsumerWorld by calling wait(), and waits to reacquire the lock on ProducerConsumerWorld after Producer has consumed.
Note:
Calling notify() doesn't release a lock until the thread moves out of the synchronized block, or wait() is called, thus releasing the lock.
Source: Oracle's OCA/OCP Java SE 7 Study Guide Page 760
Code:
import java.util.Scanner;
public class ThreadApp {
public static void main(String[] args) throws InterruptedException {
ProducerConsumerWorld p = new ProducerConsumerWorld();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
class ProducerConsumerWorld{
boolean consumed = false;
public void producer() throws InterruptedException{
System.out.println("Producer thread started running");
synchronized (this) {
while(this.consumed == true){ // Consumer has consumed and is waiting for produce
System.out.println("Resumed Producing");
this.consumed = false;
notify();
wait();
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(this.consumed == false){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
this.consumed = true;
System.out.println("consumed all");
notify();
wait();
}
}
}
}
This gives me an output like,

why i am getting error while implementingInterThread Communication in java using wait and notify?

I am implementing a simple example of SimpleInterThreadCommunication and have used wait and notify.
I am getting an error on total in InterThread class can anyone explain why
public class InterThread
{
public static void main(String s[])throws InterruptedException
{
Thread b=new Thread();
b.start();
Thread.sleep(10);
synchronized (b)
{
System.out.println("Main thread trying to call wait");
b.wait();
System.out.println("Main thread got notifies");
System.out.println(b.total); //error here total cannot be resolved to a field
}
}
}
class ThreadB extends InterThread
{
int total=0;
public void run()
{
synchronized(this)
{
System.out.println("child thread got notifies");
for(int i=0;i<3;i++)
{
total=total+i;
}
System.out.println("child thread ready to give notification");
this.notify();
}
}
}
You need to create Object of ThreadB class then you can access total field.
it is not visible to Thread class object.
You have created b object Of Thread class and in Thread class no any such field named as total available.
change your code something like below:
ThreadB b1=new ThreadB();
System.out.println(b1.total);
Answer i made changes after suggestion from helpful people
Here is the corrected code
public class InterThread
{
public static void main(String s[])throws InterruptedException
{
ThreadB b=new ThreadB(); //correction 1
b.start();
Thread.sleep(10);
synchronized (b)
{
System.out.println("Main thread trying to call wait");
b.notify(); //correction2
System.out.println("Main thread got notifies");
System.out.println(b.total);
}
}
}
class ThreadB extends InterThread
{
int total=0;
public void run()
{
synchronized(this)
{
System.out.println("child thread got notifies");
for(int i=0;i<3;i++)
{
total=total+i;
}
System.out.println("child thread ready to give notification");
try
{
System.out.println("child thread ready trying to call wait");
this.wait(); //corrected 3
}
catch(InterruptedException e)
{
System.out.println("interrupted Exception");
}
}
}
}

is this a thread deadlock

I wanted to intentionally do/test java thread deadlock state so I made a following sample code:
public class TestDeadLock extends Thread{
private Integer a=new Integer(9);
public void run(){
if(Thread.currentThread().getName().equals("t1")){
XXXX();
}
else{
ZZZZ();
}
}
public void XXXX(){
System.out.println("inside XXXX");
synchronized(a){
a++;
ZZZZ();
}
System.out.println("xxxxxxxxxxxxxxxxxxx");
//ZZZZ();
}
public synchronized void ZZZZ(){
System.out.println("inside ZZZZ");
synchronized(a){
a--;
XXXX();
}
System.out.println("zzzzzzzzzzzzzzzzzzzzz");
}
public static void main(String[] args) throws InterruptedException {
TestDeadLock tdl=new TestDeadLock();
Thread t1=new Thread(tdl);
Thread t2=new Thread(tdl);
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
Thread.sleep(1000);
System.out.println("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="+tdl.a);
}
}
The output came out to be like :
inside XXXX
inside ZZZZ
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=10
output is NOT exiting.
I wanted to know, was it due to threads reached Dead Lock state? Is it a right example to experience Dead Lock. Suggest or correct me if I am wrong.
No, you are not experiencing a dead lock. You are encountering a StackOverflowError because you are running into an infinite loop.
Note that your method
public synchronized void ZZZZ() {
System.out.println("inside ZZZZ");
XXXX(); // run-time exception
}
is equivalent to
public void ZZZZ() {
synchronized(this) {
System.out.println("inside ZZZZ");
XXXX(); // run-time exception
}
}
You are not causing a dead lock because you are working on two different instances.
Thread 1 locks t1, thread 2 locks t2.
Your ZZZZ() method contains a call to XXXX() method and vice-versa.
Thus, you have created a never-ending chain of calls that goes: ZZZZ() -> XXXX() -> ZZZZ() -> XXXX() -> etc.
Eventually, your stack will grow too large from all the nested method calls that get pushed onto the stack. Hence, the exceptions that you are getting.
Try this example:
public class TestThread {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String args[]) {
ThreadDemo1 T1 = new ThreadDemo1();
ThreadDemo2 T2 = new ThreadDemo2();
T1.start();
T2.start();
}
private static class ThreadDemo1 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 1: Holding lock 1...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}
}
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (Lock2) {
System.out.println("Thread 2: Holding lock 2...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (Lock1) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
}
This accurately shows threads reaching deadlock.
Here is the solution:
public class TestThread {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String args[]) {
ThreadDemo1 T1 = new ThreadDemo1();
ThreadDemo2 T2 = new ThreadDemo2();
T1.start();
T2.start();
}
private static class ThreadDemo1 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 1: Holding lock 1...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}
}
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 2: Holding lock 1...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
}
Source: http://www.tutorialspoint.com/java/java_thread_deadlock.htm
Example given by Jase Pellerin is a good example of dead lock but it has one mistake (Sorry Jase Pellerin , i am sure you did it unintetionally) . Here, both methods are trying to get hold of Lock1 first and then Lock2. I think it should be other way around.
Thread1{
synchronized (Lock1) {
synchronized (Lock2) {}
}
}
Thread2{
synchronized (Lock2) {
synchronized (Lock1) {}
}
}

Why doesn't it create a deadlock?

Please refer to the code below
package com.test;
public class DeadLock {
private void method1() {
synchronized (Integer.class) {
method2();
}
}
private void method2() {
synchronized (Integer.class) {
System.out.println("hi there");
}
}
public static void main(String[] args) {
new DeadLock().method1();
}
}
As per my understanding, the code in method2 should not be executed in any case, since method1 holds the lock on Integer.class and method2 tries to access the lock on Integer.class again. But to my surprise, the code runs fine and it prints "hi there" to the console. Can someone clarify?
Locks are owned by threads. If your thread already owns a lock, Java assumes that you don't need to acquire it a second time and just continues.
You'll get a deadlock if you start a second thread in method1() while holding the lock and the second thread executes the method method2().
If you prefer code, then synchronized works like this:
Lock lock = Integer.class.getLock();
boolean acquired = false;
try {
if(lock.owner != Thread.currentThread()) {
lock.acquire();
acquired = true;
}
...code inside of synchronized block...
} finally {
if(acquired) lock.release();
}
Here is code to demonstrate the deadlock. Just set runInThread to true:
package com.test;
public class DeadLock {
private void method1() {
synchronized (Integer.class) {
boolean runInThread = false;
if( runInThread ) {
Thread t = new Thread() {
#Override
public void run() {
method2();
}
};
t.start();
try {
t.join(); // this never returns
} catch( InterruptedException e ) {
e.printStackTrace();
}
} else {
method2();
}
}
}
private void method2() {
System.out.println("trying to lock");
synchronized (Integer.class) {
System.out.println("hi there");
}
}
public static void main(String[] args) {
new DeadLock().method1();
}
}
It seems you have misunderstood the concept.
A method never acquires a lock, the instance on which the method is invoked serves as a lock in case of synchronized method and in case of synced block the thread acquires the lock on specified object.
Here the instance acquires the lock on Integer.class and then it goes on to execute method2.
There is no case of deadlock as in your case thread continues for the execution of the method that you're calling inside method1. So there is no deadlock that happens.
your code is equivalent to:
synchronized (Integer.class) {
synchronized (Integer.class) {
System.out.println("hi there");
}
}
if the thread acquired the lock and entered the first synchronized block it will have no problem accessing the 2nd
to produce a deadlock the call to method2 should be executed by a different thread.
synchronized (Integer.class) {
method2();
}
when you calling this method2(); then its not giving lock to any kind of mehtod its continues goes to the method that you are calling means this.
private void method2() {
synchronized (Integer.class) {
System.out.println("hi there");
}
}
and after completing its returning. so there is no case of dead lock. hope this explanation helps.
As already said, one thread can access more than one synchronised blocks when no other thread already blocks it. In that situation the same thread can reenter synchronised block because it already holds it from method1.
To cause the deadlock you have to use two thread at least and two different locks. It have to access two locks in the reverse order. Check out that code:
private void method1() throws InterruptedException
{
synchronized (Integer.class)
{
System.out.println(Thread.currentThread().getName() + " hi there method 1");
Thread.sleep(1000);
method2();
}
}
private void method2() throws InterruptedException
{
synchronized (Double.class)
{
System.out.println(Thread.currentThread().getName() + " hi there method 2");
Thread.sleep(1000);
method1();
}
}
public static void main(String[] args) throws InterruptedException
{
new Thread()
{
#Override
public void run()
{
try
{
new DeadLock().method1();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}.start();
new DeadLock().method2();
}

Understanding the use of Synchronized

I am trying to understand the use of Synchronized block.
In the below program, Inside a produce and consumer method I have created a synchronized block and if I lock it by using lock1(object). I am getting the following error, why is this, why am i getting this error?
I am aware that by replacing lock1 by this(same class). I can get rid of the error. I still want to know why this error as everything seems very logical to me.
Program
import java.util.Scanner;
public class Worker {
private Object lock1 = new Object();
private Object lock2 = new Object();
public void produce() throws InterruptedException {
synchronized (lock1) {
System.out.println("Producer thread running");
wait();
System.out.println("Producer resumed");
}
}
public void consumer() throws InterruptedException {
Scanner scanner = new Scanner(System.in);
Thread.sleep(2000);
synchronized (lock1) {
System.out.println("Waiting for return key");
scanner.nextLine();
System.out.println("return key is pressed");
notify();
Thread.sleep(5000);
System.out.println("Consumer is over");
}
}
public void main() {
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
try {
consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:503)
at Worker.produce(Worker.java:14)
at Worker$1.run(Worker.java:43)
at java.lang.Thread.run(Unknown Source)
synchronized (lock1) {
System.out.println("Producer thread running");
wait();
System.out.println("Producer resumed");
}
You acquire the monitor of lock1 and then proceed to wait on this which fails because, as the documentation of Object#wait states,
The current thread must own this object's monitor.
You need to call lock1.wait() and lock1.notify(). You can only call wait() or notify() on an object on which you hold the lock (lock1 in this case).
In the synchronized block the current thread is the owner of the synchronization object's monitor.
In your case it is lock1.
According to the javadoc of Object.wait()
The current thread must own this object's monitor.
and Object.notify()
This method should only be called by a thread that is the owner of this object's monitor.
you must change your code to
synchronized (lock1) {
System.out.println("Producer thread running");
lock1.wait();
System.out.println("Producer resumed");
}
and
synchronized (lock1) {
System.out.println("Waiting for return key");
scanner.nextLine();
System.out.println("return key is pressed");
lock1.notify();
Thread.sleep(5000);
System.out.println("Consumer is over");
}
To call wait() and notify() you need to own the object's monitor you want to call these two methods.
Link to javadoc Object.wait()
Citation from above link:
The current thread must own this object's monitor.
I am showing how I fixed the producer-consumer problem.
I have using different way then you. I think this will help you..
And the to make any block or method synchronized their are some condition :
synchronized methods prevent more than one thread from accessing an
object's critical method code simultaneously.
You can use the synchronized keyword as a method modifier, or to start a
synchronized block of code.
To synchronize a block of code (in other words, a scope smaller than the
whole method), you must specify an argument that is the object whose lock
you want to synchronize on.
While only one thread can be accessing synchronized code of a particular
instance, multiple threads can still access the same object's unsynchronized code.
static methods can be synchronized, using the lock from the
java.lang.Class instance representing that class.
All three methods—wait(), notify(), and notifyAll()—must be
called from within a synchronized context! A thread invokes wait() or
notify() on a particular object, and the thread must currently hold the lock
on that object.
class P implements Runnable{
Data d;
P(Data d){
this.d = d;
new Thread(this,"Producer").start();
}
public void run(){
for(int i=0; i<=20; i++){
d.set(i);
System.out.println("put -> "+i);
}
}
}
class C implements Runnable{
Data d;
C(Data d){
this.d = d;
new Thread(this,"Consumer").start();
}
public void run(){
for(int i=0; i<=20; i++){
int n = d.get();
System.out.println("get -> "+n);
}
}
}
class Data{
int n;
boolean valueset=false;
synchronized void set(int n){
if(valueset){
try{
wait();
}catch(Exception e){
System.out.println("set -> Exception "+e);
}
}
this.n = n ;
valueset=true;
notify();
}
synchronized int get(){
if(!valueset){
try{
wait();
}catch(Exception e){
System.out.println("get -> Exception "+e);
}
}
valueset=false;
notify();
return n ;
}
}
class PC{
public static void main(String[] args){
Data d = new Data();
new P(d);
new C(d);
}
}
You can download solution of producer consumer from here :
https://www.mediafire.com/?52sa1k26udpxveu

Categories

Resources