Search code examples
javamultithreadingdeadlocksemaphore

Java Semaphore methods not working as expected


I am new to the consumer producer problem and the Semaphore. The following code is getting Deadlocked in the condition that Producer thread gets stuck when it is acquiring the permit again just after adding in the queue..

Only this is the case when program is deadlocked.

public class UsingSemaphore {

    volatile static boolean check = true;

    public static void main(String args[]) throws InterruptedException {

        Semaphore semCon = new Semaphore(0);

        Semaphore semProd = new Semaphore(1);

        Queue<Integer> q = new LinkedList<>();


        // Producer lambda
        Runnable producer = () -> {
            while (check) {
                try {
                    semProd.acquire();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    
                    Random rand = new Random();
                    q.add(rand.nextInt(10));    
                }finally {
                    semCon.release();

                }
            }   
        };
                //Consumer lambda
        Runnable consumer = () -> {
            while (check) {
                try {

                    semCon.acquire();

                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                try {
                    System.out.println("Consumer item " + q.remove());
                
                }finally {
                    semProd.release();

                }
            }
        };  
        
        ThreadGroup pg = new ThreadGroup("PG");
        ThreadGroup cg = new ThreadGroup("CG");

        Thread p1 = new Thread(pg, producer, "p1");

        Thread c1 = new Thread(cg, consumer, "c1");


        p1.start();

        c1.start();

        Thread.sleep(10);
        check = false;
    }
}

The consumer thread does not run in the test case where producer goes to acquire permit... please somebody help


Solution

  • Your problem is I think the lack of synchronization around the check flag that allows your loop to start or end.

    It is possible for instance that the producer starts the loop and waits for semProd.acquire() (on its second iteration) but the consumer never actually started because the check flag was evaluated to false.

    When the loops end, both the consumer and the producer must end at the right time or a deadlock can occur when you consider the sequence of events:

    C1:   semProd.release()
    P1:   semProd.acquire() -> OK
    P1:   q.add()
    P1:   semCon.release()
    P1: while(check) -> IN
    P1:   semProd.acquire() -> wait
    MAIN: check <- false
    C1: while(check) -> OUT
    C1: stops
    P1: deadlocked
    

    Same applies the other way around if C1 is trying to acquire semCon .