I have the following Java code:
import java.util.concurrent.*;
class Foo{
static Semaphore s = new Semaphore(1);
public void fun(final char c, final int r){
new Thread(new Runnable(){
public void run(){
try{
s.acquire(r);
System.out.println(c+"_"+r);
s.release(r+1);
} catch(Exception e){ e.printStackTrace(); }
}
}).start();
}
}
class ths{
public static void main(String[]args) throws Exception{
Foo f = new Foo();
f.fun('B',2);
f.fun('F',6);
f.fun('A',1);
f.fun('C',3);
f.fun('D',4);
f.fun('E',5);
}
}
Ideally, this should print A_1 through F_6 in order and exit, but for some reason that doesn't happen. It usually prints A_1 and B_2 and then it gets stuck.
I can't find anything obviously wrong with my code. Any suggestions?
The implementation of semaphore with a waiting queue may result in a satiation where two more processes are waiting indefinitely for an event that can be caused only by one of the waiting processes. When such a state is reached that process are said to be deadlocked.
Deadlock in Java is a condition where two or more threads are blocked forever, waiting for each other. This usually happens when multiple threads need the same locks but obtain them in different orders. Multithreaded Programming in Java suffers from the deadlock situation because of the synchronized keyword.
acquire() Acquires a permit from this semaphore, blocking until one is available, or the thread is interrupted. void. acquire(int permits) Acquires the given number of permits from this semaphore, blocking until all are available, or the thread is interrupted.
The basic problem is that acquire(int permits)
does not guarantee that all permits will be grabbed at once. It could acquire fewer permits and then block while waiting for the rest.
Let's consider your code. When, say, three permits become available there's nothing to guarantee that they will be given to thread C
. They could, in fact, be given to thread D
to partially satisfy its acquire(4)
request, resulting in a deadlock.
If you change the code like so, this fixes the problem for me:
public void fun(final char c, final int r){
new Thread(new Runnable(){
public void run(){
try{
while (!s.tryAcquire(r, 1, TimeUnit.MILLISECONDS)) {};
System.out.println(c+"_"+r);
s.release(r+1);
} catch(Exception e){ e.printStackTrace(); }
}
}).start();
}
(On second thoughts, the above is also broken since there's no guarantee the correct thread will ever get the permits -- it could keep trying and timing out indefinitely.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With