Reputation: 23517
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;
}
...
Upvotes: 1
Views: 90
Reputation: 9324
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!");
}
}
Upvotes: 0
Reputation: 1266
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:
What you're doing here is basic synchronization, only allowing one object to access sharedBuffer
at a time.
Upvotes: 0
Reputation: 500743
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.
Upvotes: 3