I have a simple question about managing Threads. I have 3 process that share the same Semaphore with one permit. in normal situation, the first process takes this permit and release two permit tho the second process. The second process release 3 permits to the third process. I given an example to illustrate my problem.
First one:
public class Process0 extends Thread{
Semaphore s;
public Process0(Semaphore s){
this.s = s;
}
public void run(){
try {
sleep(20000);
s.acquire();
System.out.println("hello");
} catch (InterruptedException ex) {
Logger.getLogger(Process.class.getName()).log(Level.SEVERE, null, ex);
}
s.release(2);
}
}
Second Process:
public class Process1 extends Thread{
Semaphore s;
public Process1(Semaphore s){
this.s = s;
}
public void run(){
try {
this.sleep(10000);
s.acquire(2);
System.out.println("Hello 2");
} catch (InterruptedException ex) {
Logger.getLogger(Process1.class.getName()).log(Level.SEVERE, null, ex);
}
s.release(3);
}
}
And last one:
public class Process2 extends Thread{
Semaphore s;
public Process2(Semaphore s){
this.s = s;
}
public void run(){
try {
System.out.println("Acquire process 3 ");
s.acquire(3);
System.out.println("Hello 3");
} catch (InterruptedException ex) {
Logger.getLogger(Process2.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
The problem is. When i run this three process and be sure that process 3 is the first that excute the acquire
. I will have a deadlock. Process 2 never print "Hello 3" and process 1 never print "Hello 2".Why ?
Semaphore s = new Semaphore(1);
Process0 p = new Process0(s);
Process1 p1 = new Process1(s);
Process2 p2 = new Process2(s);
p.start();
p1.start();
p2.start();
Your Semaphore is constructed as
new Semaphore(1)
, which only has one permit available to be acquired. The calls.acquire(3)
will never return since the semaphore will never have three permits available. The attempt to acquire a single permit byProcess
also blocks since acquisitions are ordered andProcess2
arrived "first":The
release
method javadoc states that an acquisition can happen whenThis minimal, single-thread example will show you:
The solution to this is to use
Semaphore.acquire()
which requests one permit, orSemaphore.acquire(1)
which also requests only one permit.You also need to make sure that you acquire and release the same amount of permits, unless you have a very good reason to misuse
Semaphore
. From Javadoc:Additionally, it seems that you might be using the wrong synchronizer for this task. You could use a
CyclicBarrier
or other class usable for synchronization.