Please Explain Deadlock Concept - java

I was going through Java threads, specially the deadlock concept, I have found this below code:
public static void main(String... a) {
final String o1 = "Lock ";
final String o2 = "Step ";
Thread th1 = new Thread() {
public void run() {
while (true) {
synchronized (o1) {
synchronized (o2) {
System.out.println(o1 + o2);
}
}
}
}
};
Thread th2 = new Thread() {
public void run() {
while (true) {
synchronized (o2) {
synchronized (o1) {
System.out.println(o2 + o1);
}
}
}
}
};
new Thread(th1).start();
new Thread(th2).start();
}
Please explain what the program is doing as per my understandings a lock has been taken by one thread and trying to take another lock and the same is done by other thread , and when finally when we start two threads both got stuck up, Is there any other way to create deadlock of the above program, please advise and also the lock which is being taken in the above code is it the instance level lock.

Consider the following scenario:
th1 locks o1 and is interrupted before it gets a chance to lock o2;
th2 locks o2 and tries to lock o1.
Neither thread can make further progress, and you have a deadlock.
The original version of your code (before the edit) had no possibility of deadlock, since both threads acquired the two locks in the same order (o1 then o2).

To create Deadlock, you need to create a situation where multiple threads are waiting for locks held by other threads. For example:
Thread 1 needs Lock1 and Lock2
Requests in order: Lock1, Lock2
Thread 2 needs Lock1 and Lock2
Requests in order: Lock2, Lock1
Thread 1 requests Lock1.
Thread 2 requests Lock2.
Thread 1 gets Lock1.
Thread 2 gets Lock2.
Thread 1 requests Lock2.
Thread 2 requests Lock1.
Thread 1 cannot have Lock2, Thread 2 is holding it. /Thread 1 waits...
Thread 2 cannot have Lock1, Thread 1 is holding it. /Thread 2 waits...
In your (first, unedited) example, both threads request the locks they need in the same order and this is very important. If Thread1 gets Lock1, Thread2 cannot get Lock2 and create Deadlock, because it is still waiting for Lock1. Deadlock is avoided, because both threads attempt to acquire locks in the same order.
In your (new, edited) example, Deadlock can happen as explained above.

Based on your edited post, th1 could acquire o1 while th2 could acquire o2. Then both threads are waiting for the other to release the lock they have not acquired yet, and it never happens ==> deadlock.

Related

Is a reentrant lock released when calling its condition.await?

I have the following code:
public class Synchronizer {
private final Lock lock = new ReentrantLock();
private final Condition done = lock.newCondition();
private boolean isDone = false;
private void signalAll() {
lock.lock(); // MUST lock!
try {
isDone = true; // To help the await method ascertain that it has not waken up 'spuriously'
done.signalAll();
}
finally {
lock.unlock(); // Make sure to unlock even in case of an exception
}
}
public void await() {
lock.lock(); // MUST lock!
try {
while (!isDone) { // Ascertain that this is not a 'spurious wake-up'
done.await();
}
}
finally {
isDone = false; // for next time
lock.unlock(); // Make sure to unlock even in case of an exception
}
}
}
Suppose thread 1 calls synchornizer.await() and acquires the lock via the
lock.lock();
and blocks on the
done.await();
Then another thread 2 calls synchronizer.signalAll() in order to signal thread 1. My question is how is thread 2 ever able to acquire the lock by calling
lock.lock();
before calling
done.signallAll();
when the lock was initially acquired by thread 1?
I found the same question here:
Waiting on a condition in a reentrant lock
The answer says:
Both Lock and synchronized temporarily allow others to obtain the lock
when they are waiting. To stop waiting, a thread have to re-acquire
the lock.
I am trying to understand does this mean that thread 2 would not be able to acquire the lock if thread 1 did not call done.await()?
Also the answer states that:
Note: They don't release it fully and if you take a stack trace you
can have multiple threads which appear to be holding the lock at once,
but at most one of them will be running (the rest will be waiting)
Yet the documentation for Condition.await() states that:
The lock associated with this Condition is atomically released
So is the lock released or not and what "They don't release it fully" mean?
Thread 1 (T1) will acquire lock at #await() lock.lock() call
T1 will release lock at #await() done.await(). T1 will park untill signaled or interupted or "spurious waked"*
T2 will acquire lock at #signallAll() lock.lock
T2 will signal waking up #signallAll() done.signalAll
T2 will release lock #signallAll() lock.unlock
T1 will wake up at #await() done.await()
T1 will acquire lock #await() done.await()
T1 will release lock #await() lock.unlock()
T1 could be "spurious waked" at any point of running T2. But this will happen within done.await call. Control will never be retured to caller code unless associated lock is unlocked and other conditions for releasing are not right (thread must be signaled or interupted).

Why await of Condition releases the lock but signal does not?

I write the below code to test when will the thread is awake when it is waiting for a Condition object.
But I find I have to unlock after I call signal(). Lock is not release by this method, while await() will release this lock .
This is from Condition#await
The lock associated with this Condition is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:
And this is from Conditon#signal
Wakes up one waiting thread.
If any threads are waiting on this condition then one is selected for waking up. That thread must then re-acquire the lock before
returning from await.
But in my code, this is not true, until we unlock the lock. Why it is design like this? Since in my opinion, when we decide to to signal the others, we should not hold the lock any more,am I wrong?
Since we can do many things between calling signal and unlock ,say I sleep 10 seconds, what exactly the time java signal the other thread? Is there a another background thread who is working between we signal and unlock?
public class WorkerThread extends Thread{
#Override
public void run() {
Monitor.lock.lock();
while (!Monitor.isConditionTrue){
try {
Monitor.condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("THREAD ID "+this.getId()+"-------working --------");
System.out.println("------singnall--------");
Monitor.isConditionTrue=true;
Monitor.condition.signal();
try {
Thread.sleep(3000);//here, the thread is sleeping while another thread is not awaken since the lock is not releases
System.out.println("------unlock--------");
Monitor.lock.unlock();//now the other thread is awaken, if I do not explicitly unlock , no thread will be awaken.
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Monitor {
static ReentrantLock lock = new ReentrantLock();
static Condition condition = lock.newCondition();
static volatile boolean isConditionTrue = true;
public static void main(String args[]) {
Thread t1 = new WorkerThread();
Thread t2 = new WorkerThread();
t1.start();
t2.start();
Thread.sleep(2000);
lock.lock();
isConditionTrue=true;
condition.signalAll();
lock.unlock();
}
}
OUTPUT:
THREAD ID 9-------working --------
------singnall--------
------unlock--------
THREAD ID 10-------working --------
------singnall--------
------unlock--------
You have missed this sentence in Contition#await:
In all cases, before this method can return the current thread must re-acquire the lock associated with this condition. When the thread returns it is guaranteed to hold this lock.
In other words, you must explicitly release the lock after await, just as with signal.
Why this mechanism is sound: if you first released the lock, then signaled, you'd be open to race conditions where other threads made changes between releasing the lock and the signal reaching a parked thread. The way the mechanism works, first a definite thread is chosen to be awoken by the signal, then it waits for the lock, then the signaling thread releases it, then the awoken thread goes on.
You might argue that signal could do all of this internally, but then:
the API would become confusing: there would be more than one method releasing the lock;
the APi would become more restrictive and preclude any use cases where the thread wants to do something more before releasing the lock, such as atomically issuing more signals.

Does synchronized park a concurrent thread like Lock.lock() does?

When we call either lock.lock() or try to enter a synchronized block then our thread blocks if some other thread has already taken that lock. Now my question is, when we look at the implementation of lock.lock() it delegates acquiring lock to AQS which actually parks the current thread (so that it cannot be scheduled further by scheduler).
Is it the same case with synchronized blocking also?
I even think my thread status are also different. For example, if my thread is blocked on synchronized block it will be BLOCKING while if I have called
lock.lock(), then it will be WAITING. Am I right?
My Concern is the difference between the below two locking strategies in aspects of Thread.status and performance improvement by parking instead of busy waiting
ReentrantLock.lock();
synchronize { /*some code */ }
BLOCKING - is blocked on a resource, cannot be interrupted
WAITING - is blocked on a resource, but can be interrupted or notified or unparked.
As you can see WAITING is better for control from another processed. e.g. if two threads are deadlocked you could break a lock() with an interrupt. With a two thread using synchronized you are stuck.
The behaviour of the synchronized vs lock is very similar and the exact details change between major revisions.
My advise is to use
synchronized for simpler code where you need thread safety but have a very low lock contention.
use Lock where you have identified you have lock contention, or you need additional functionality like tryLock.
If you do
final Lock lock = new ReentrantLock();
lock.lock();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
Thread.sleep(100);
System.out.println(t + " is " + t.getState());
lock.unlock();
prints
Thread[Thread-0,5,main] is WAITING
Thread.State states
Thread state for a waiting thread. A thread is in the waiting state due to calling one of the following methods:
Object.wait with no timeout
Thread.join with no timeout
LockSupport.park
A thread in the waiting state is waiting for another thread to perform a particular action. For example, a thread that has called Object.wait() on an object is waiting for another thread to call Object.notify() or Object.notifyAll() on that object. A thread that has called Thread.join() is waiting for a specified thread to terminate.
Calling upon lock or lockInterruptibly will put the thread in WAITING state:
Thread state for a waiting thread. A thread is in the waiting state due to calling one of the following methods:
Object.wait with no timeout
Thread.join with no timeout
LockSupport.park
The following code starts four threads, first two (A,B) run the same code and lock some monitor via the lock method. The other two (C,D) also run the same code, but they lock some another monitor via the lockInterruptibly method:
public static synchronized void dumpThreadState(List<Thread> threads) {
System.out.println("thread state dump start");
for (Thread t: threads) {
System.out.println(t.getName()+" "+t.getState());
}
System.out.println("thread state dump end\n");
}
public static void main(String[] args) throws InterruptedException {
final Lock lock = new ReentrantLock();
final Lock anotherLock = new ReentrantLock();
List<Thread> threads = new LinkedList<Thread>();
Runnable first = new Runnable() {
#Override
public void run() {
try {
lock.lock();
}
catch (Exception ex) {
System.out.println(Thread.currentThread().getName()+" processing exception "+ex.getClass().getSimpleName());
}
while (true);
}
} ;
Runnable second = new Runnable() {
#Override
public void run() {
try {
anotherLock.lockInterruptibly();
}
catch (InterruptedException ex) {
System.out.println(Thread.currentThread().getName()+" was interrupted");
}
while (true);
}
};
threads.add(new Thread(first,"A"));
threads.add(new Thread(first,"B"));
threads.add(new Thread(second,"C"));
threads.add(new Thread(second,"D"));
dumpThreadState(threads);
for (Thread t: threads) {
t.start();
}
Thread.currentThread().sleep(100);
dumpThreadState(threads);
System.out.println("interrupting " + threads.get(1).getName());
threads.get(1).interrupt();
dumpThreadState(threads);
System.out.println("interrupting " + threads.get(3).getName());
threads.get(3).interrupt();
Thread.currentThread().sleep(100);
dumpThreadState(threads);
for (Thread t: threads) {
t.join();
}
}
It outputs:
thread state dump start
A NEW
B NEW
C NEW
D NEW
thread state dump end
thread state dump start
A RUNNABLE
B WAITING
C RUNNABLE
D WAITING
thread state dump end
interrupting B
thread state dump start
A RUNNABLE
B WAITING
C RUNNABLE
D WAITING
thread state dump end
interrupting D
D was interrupted
thread state dump start
A RUNNABLE
B WAITING
C RUNNABLE
D RUNNABLE
thread state dump end
As it can be seen the thread locked via the lock method can not be interrupted, while thread locked with lockInterruptibly can.
In the other example three threads are started, the first two (A,B) run the same code and lock upon the same monitor via the synchronized block. The third thread locks on another monitor but waits via the wait method:
public static void main(String[] args) throws InterruptedException {
final Object lock = new Object();
final Object anotherLock = new Object();
List<Thread> threads = new LinkedList<Thread>();
Runnable first = new Runnable() {
#Override
public void run() {
synchronized(lock) {
while (true);
}
}
} ;
Runnable second = new Runnable() {
#Override
public void run() {
synchronized(anotherLock) {
try {
anotherLock.wait();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
};
threads.add(new Thread(first,"A"));
threads.add(new Thread(first,"B"));
threads.add(new Thread(second,"C"));
dumpThreadState(threads);
for (Thread t: threads) {
t.start();
}
Thread.currentThread().sleep(100);
dumpThreadState(threads);
for (Thread t: threads) {
t.join();
}
}
It outputs:
thread state dump start
A NEW
B NEW
C NEW
thread state dump end
thread state dump start
A RUNNABLE
B BLOCKED
C WAITING
thread state dump end
Thread C ended up in WAITING state while thread B ended up in BLOCKING state:
Thread state for a thread blocked waiting for a monitor lock. A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or reenter a synchronized block/method after calling Object.wait.
EDIT:
Here is a real nice UML diagram of thread states.
Parking a thread and synchronized blocking are very different. When you try and enter a synchronized block, you are explicitly attempting to acquire a monitor on an object instance. If you can not acquire the monitor, your thread will go into the BLOCKING state until the monitor is available. Parking is more similar to the Object.wait() method in that the code knows that it can't continue until some other condition becomes true. There's no sense in blocking here because it would be fruitless because my condition for continuing on is currently true. At this point I go into the WAITING or TIMED_WAITING (depends on how the wait is issued) state until I am notified (via something like notify(), notifyAll() or unpark()). Once my condition becomes true I come out if my wait state and then probably attempt to acquire monitors and go into BLOCKING if I need them. If I get my monitors, I go into RUNNING and continue on my merry way
So waiting is really about knowing that I can't do something and having some other thread notify me when it thinks I can. It can lead to blocking after I wake up though. Blocking is just competing for access to a monitor without an explicit other prerequisite condition.
When lock() is called on a Lock instance, the calling thread is actually put into a wait state and is not blocking. The benefit here is that this wait state can be interrupted and this helps to avoid deadlocks. With something like the Lock class, you have a bunch of options on desired waiting behaviors via tryLock(), tryLock(long,TimeUnit), lock() and lockInterruptibly(). You can specify things like how long you want to wait and if you can be interrupted via which method you call. With synchronized code, you don't have such options. You're blocking and you're stuck blocking until some thread gives up the monitor you want and if it never does, you are deadlocked. That's why since Java 5 and the concurrent package, you should avoid using the synchronized keyword and instead try and implement similar semantics with things like Lock and Condition.

Why does this NOT cause a dead-lock

Why does the following piece of code not cause a deadlock?
From my limited understanding of multi-threading programming, when getBar1() is called, sharedBuffer would be 'locked', hence, when the method tries to call getBar2(), the thread would have to wait for sharedBuffer (which is held by itself!). In other words, getBar2() cannot return until getBar1() has (and released sharedBuffer). But on the other hand, getBar1() cannot return either because it is waiting for getBar2() to return.
==> Deadlock. (But in actuality, it is not, which is why I am confused)
...
Foo sharedBuffer = new Foo();
Bar1 getBar1()
{
Bar1 bar1;
synchronized (sharedBuffer)
{
bar1 = sharedBuffer.getBar1();
if (bar1 == null)
bar1 = new Bar1(sharedBuffer, getBat2());
sharedBuffer.setBar1(bar1);
}
return bar1;
}
Bar2 getBar2()
{
Bar2 bar2;
synchronized (sharedBuffer)
{
bar2 = sharedBuffer.getBar2();
if (bar2 == null)
bar2 = new Bar2();
}
return bar2;
}
...
Java's monitors are recursive, meaning that the same thread can acquire the same locks several times.
From the JLS (ยง17.1 Synchronization):
A thread t may lock a particular monitor multiple times; each unlock reverses the effect of one lock operation.
A deadlock happens when concurrent operations attempt to lock two or more resources in a different order, and they are both stuck waiting for the resource locked by the other.
For example, threads T1 and T2 synchronize on resources R1 and R2:
T1 synchronizes on R1.
scheduler decides that T2 should run
T2 synchronizes on R2.
T2 attempts to synchronize on R1; it's forced to wait until T1 relinquishes the lock.
scheduler sees that T2 can't continue running, so allows T1 to run
T1 attempts to synchronize on R2; it's forced to wait until T2 relinquishes the lock.
neither thread can proceed
What you're doing here is basic synchronization, only allowing one object to access sharedBuffer at a time.
It doesn't deadlock because you really only have a single lock. In both functions, you're locking on sharedBuffer. When the first thread calls getBar1(), it locks on sharedBuffer. When the same thread calls getBar2(), it hits the synchronized block and already has the lock so it just enters the lock.
If you want to cause a deadlock, use two different values against which to lock. Then, you'll only see it if the timing lines up properly. If you want to force a deadlock, make sure the first thread sleeps long enough for the second thread to get a lock.
Here's some code that will deadlock... (untested, prolly has typos). This should work because a different thread has the lock than the one that wants the lock.
public class Deadlock extends Thread
{
private Deadlock other;
private String name;
public static void main(String[] args)
{
Deadlock one = new Deadlock("one");
Deadlock two = new Deadlock("two");
one.setOther(two);
two.setOther(one);
one.start();
two.start();
}
public setOther(Deadlock other){ this.other = other; }
public void run() {
deadlock();
}
public synchronized deadlock() {
System.out.println("thread " + this.name + " entering this.deadlock()");
sleep(1000); // adjust as needed to guarantee deadlock
System.out.println("thread " + this.name + " calling other.deadlock()");
other.deadlock(this.name);
System.out.println(name + " - deadlock avoided!");
}
}

A thread holding multiple lock goes into wait() state. Does it release all holding locks?

I wrote this program to check if a thread t1 holding lock on two different objects :
Lock.class and MyThread.class goes into waiting mode on MyThread.class instance using MyThread.class.wait().It does not release lock on Lock.class instance. why so ? I have been thinking that once a thread goes into wait mode or it dies it releases all the acquired locks.
public class Lock {
protected static volatile boolean STOP = true;
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
Thread t1 = new Thread(myThread);
t1.start();
while(STOP){
}
System.out.println("After while loop");
/*
*
*/
Thread.sleep(1000*60*2);
/*
* Main thread should be Blocked.
*/
System.out.println("now calling Check()-> perhaps i would be blocked. t1 is holding lock on class instance.");
check();
}
public static synchronized void check(){
System.out.println("inside Lock.check()");
String threadName = Thread.currentThread().getName();
System.out.println("inside Lock.Check() method : CurrrentThreadName : "+ threadName);
}
}
class MyThread implements Runnable{
public MyThread() {
}
#Override
public void run() {
try {
System.out.println("inside Mythread's run()");
classLocking();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static synchronized void classLocking() throws InterruptedException{
System.out.println("inside Mythread.classLocking()");
String threadName = Thread.currentThread().getName();
System.out.println("inside MyThread.classLocking() : CurrrentThreadName : "+ threadName);
/*
* outer class locking
*/
synchronized (Lock.class) {
System.out.println("I got lock on Lock.class definition");
Lock.STOP = false;
/*
* Outer class lock is not released. Lock on MyThread.class instance is released.
*/
MyThread.class.wait();
}
}
}
You are correct that it doesn't release the other lock. As for why, it's because it isn't safe to do so. If it was safe to release the outer lock during the call to the inner function, why would the inner function be called with the other lock held at all?
Having a function release a lock it didn't acquire behind the programmer's back would destroy the logic of synchronized functions.
Yes it is working correctly. A thread goes into waiting status releases the corresponding lock instead of all locks. Otherwise think about that: if things are like what you thought, then when a thread waits it loses all the acquired locks, which makes advanced sequential execution impossible.
The semantics of wait() is that the Thread invoking it notices that a lock was already acquired by another thread, gets suspended and waits to be notified by the thread holding the lock when the latter one releases it (and invokes notify). It doesn't mean that while waiting it releases all the locks acquired. You can see the wait's invocations as a number of barriers the thread meets on the way to acquiring all the locks it needs to accomplish an action.
Regarding the question "Why a thread doesn't release all the locks acquired when invoking wait" , I think the answer is that, doing so would make it more prone to starvation and it would also slow down the progress in a multithreaded application (All threads would give up all their locks when invoking the first wait and would have to start over when they acquire the lock they are currently waiting for. So, they would be in a permanent battle for locks.
Actually, in such a system, the only thread able to finish execution would be the one which manages to find all locks free when it needs them. This is unlikely to happen)
From JavaDoc of method wait()
The current thread must own this object's monitor. 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. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

Categories

Resources