Why doesn’t the semaphore stop thrading?

I use semaphore and I want when list size is zero thread waiting for other thread But Why doesn’t the semaphore stop thrading? Doesn’t the semaphore work like notify and wait?

result: add remove add Exception in thread “Thread-2” java.lang.IndexOutOfBoundsException: Index: 0, Size: 0

 ArrayList<String> list = new ArrayList<>();
            Semaphore semaphore = new Semaphore(0);
    
            new Producer(list, semaphore).start();
            new Producer(list, semaphore).start();
            new Customeer(list, semaphore).start();
            new Customeer(list, semaphore).start();
    //////////
        static class Customeer extends Thread {
    
            private List<String> list;
            private Semaphore semaphore;
    
            public Customeer(List<String> list, Semaphore semaphore) {
                this.list = list;
                this.semaphore = semaphore;
            }
    
            @Override
            public void run() {
    
    
                synchronized (list) {
                    if (list.size() == 0) {
                        try {
                            semaphore.acquire();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                        list.remove(0);
                        System.out.println("remove");
                }
            }
        }
    
        static class Producer extends Thread {
    
            private Semaphore semaphore;
            private List<String> list;
    
            public Producer(List<String> list, Semaphore semaphore) {
                this.list = list;
                this.semaphore = semaphore;
            }
    
            @Override
            public void run() {
    
                synchronized (list) {
    
                    list.add("hello");
                    semaphore.release();
                    System.out.println("add");
    
                }
    
            }
        }
    
    }

Answer

you seem to be confused with semaphores and synchronization. semaphores is used when you want to allow n threads to access the same resource at a time. [n can be 1] while synchronization is used if you want to allow only 1 thread to access the resource.

solution using semaphores

// Java implementation of a producer and consumer 
// that use semaphores to control synchronization. 

import java.util.concurrent.Semaphore; 

class Q { 
    // an item 
    int item; 

    // semCon initialized with 0 permits 
    // to ensure put() executes first 
    static Semaphore semCon = new Semaphore(0); 

    static Semaphore semProd = new Semaphore(1); 

    // to get an item from buffer 
    void get() 
    { 
        try { 
            // Before consumer can consume an item, 
            // it must acquire a permit from semCon 
            semCon.acquire(); 
        } 
        catch (InterruptedException e) { 
            System.out.println("InterruptedException caught"); 
        } 

        // consumer consuming an item 
        System.out.println("Consumer consumed item : " + item); 

        // After consumer consumes the item, 
        // it releases semProd to notify producer 
        semProd.release(); 
    } 

    // to put an item in buffer 
    void put(int item) 
    { 
        try { 
            // Before producer can produce an item, 
            // it must acquire a permit from semProd 
            semProd.acquire(); 
        } 
        catch (InterruptedException e) { 
            System.out.println("InterruptedException caught"); 
        } 

        // producer producing an item 
        this.item = item; 

        System.out.println("Producer produced item : " + item); 

        // After producer produces the item, 
        // it releases semCon to notify consumer 
        semCon.release(); 
    } 
} 

// Producer class 
class Producer implements Runnable { 
    Q q; 
    Producer(Q q) 
    { 
        this.q = q; 
        new Thread(this, "Producer").start(); 
    } 

    public void run() 
    { 
        for (int i = 0; i < 5; i++) 
            // producer put items 
            q.put(i); 
    } 
} 

// Consumer class 
class Consumer implements Runnable { 
    Q q; 
    Consumer(Q q) 
    { 
        this.q = q; 
        new Thread(this, "Consumer").start(); 
    } 

    public void run() 
    { 
        for (int i = 0; i < 5; i++) 
            // consumer get items 
            q.get(); 
    } 
} 

// Driver class 
class PC { 
    public static void main(String args[]) 
    { 
        // creating buffer queue 
        Q q = new Q(); 

        // starting consumer thread 
        new Consumer(q); 

        // starting producer thread 
        new Producer(q); 
    } 
} 

solution using synchronized

// Java program to implement solution of producer 
// consumer problem. 

import java.util.LinkedList; 

public class Threadexample { 
    public static void main(String[] args) 
        throws InterruptedException 
    { 
        // Object of a class that has both produce() 
        // and consume() methods 
        final PC pc = new PC(); 

        // Create producer thread 
        Thread t1 = new Thread(new Runnable() { 
            @Override
            public void run() 
            { 
                try { 
                    pc.produce(); 
                } 
                catch (InterruptedException e) { 
                    e.printStackTrace(); 
                } 
            } 
        }); 

        // Create consumer thread 
        Thread t2 = new Thread(new Runnable() { 
            @Override
            public void run() 
            { 
                try { 
                    pc.consume(); 
                } 
                catch (InterruptedException e) { 
                    e.printStackTrace(); 
                } 
            } 
        }); 

        // Start both threads 
        t1.start(); 
        t2.start(); 

        // t1 finishes before t2 
        t1.join(); 
        t2.join(); 
    } 

    // This class has a list, producer (adds items to list 
    // and consumber (removes items). 
    public static class PC { 

        // Create a list shared by producer and consumer 
        // Size of list is 2. 
        LinkedList<Integer> list = new LinkedList<>(); 
        int capacity = 2; 

        // Function called by producer thread 
        public void produce() throws InterruptedException 
        { 
            int value = 0; 
            while (true) { 
                synchronized (this) 
                { 
                    // producer thread waits while list 
                    // is full 
                    while (list.size() == capacity) 
                        wait(); 

                    System.out.println("Producer produced-"
                                    + value); 

                    // to insert the jobs in the list 
                    list.add(value++); 

                    // notifies the consumer thread that 
                    // now it can start consuming 
                    notify(); 

                    // makes the working of program easier 
                    // to understand 
                    Thread.sleep(1000); 
                } 
            } 
        } 

        // Function called by consumer thread 
        public void consume() throws InterruptedException 
        { 
            while (true) { 
                synchronized (this) 
                { 
                    // consumer thread waits while list 
                    // is empty 
                    while (list.size() == 0) 
                        wait(); 

                    // to retrive the ifrst job in the list 
                    int val = list.removeFirst(); 

                    System.out.println("Consumer consumed-"
                                    + val); 

                    // Wake up producer thread 
                    notify(); 

                    // and sleep 
                    Thread.sleep(1000); 
                } 
            } 
        } 
    } 
} 

read the resources for more clarity

semaphore: https://www.geeksforgeeks.org/producer-consumer-solution-using-semaphores-java/

synchronized: https://www.geeksforgeeks.org/producer-consumer-solution-using-threads-java/

Leave a Reply

Your email address will not be published. Required fields are marked *