Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Producer-consumer Problem using Semaphores Here, the semaphores solve the lost-w

ID: 3754987 • Letter: P

Question

Producer-consumer Problem using Semaphores Here, the semaphores solve the lost-wakeup problem: semaphore mutex 1; /* binary semaphore providing mutual exclusion */ semaphore empty N; counting semaphore, counts empty buffer slots "/ semaphore full 0; counting semaphore, counts full buffer slots "/ void producer(void) void consumer(void) while(TRUE) while(TRUE) int item- produce_item); down(); down(&mutex); // Enter CR insert-item( item): put in buffer up(&mutex); I/ Leave CR up(&full) down(&full); down(&mutex); // Enter CR int itemremove item(); remove em from bufer up(&mutex); // Leave CR up(); consume item(item); // do something with it

Explanation / Answer

// 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);

    }

}

Output:

Explanation : As you can see, the calls to put() and get( ) are synchronized, i.e. each call to put() is followed by a call to get( ) and no items are missed. Without the semaphores, multiple calls to put() would have occurred without matching calls to get(), resulting in items being missed. (To prove this, remove the semaphore code and observe the results.)

The sequencing of put() and get() calls is handled by two semaphores: semProd and semCon.

// 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);

    }

}

Output:

  Producer produced item : 0  Consumer consumed item : 0  Producer produced item : 1  Consumer consumed item : 1  Producer produced item : 2  Consumer consumed item : 2  Producer produced item : 3  Consumer consumed item : 3  Producer produced item : 4  Consumer consumed item : 4  

Explanation : As you can see, the calls to put() and get( ) are synchronized, i.e. each call to put() is followed by a call to get( ) and no items are missed. Without the semaphores, multiple calls to put() would have occurred without matching calls to get(), resulting in items being missed. (To prove this, remove the semaphore code and observe the results.)

The sequencing of put() and get() calls is handled by two semaphores: semProd and semCon.

  • Before put( ) can produce an item, it must acquire a permit from semProd. After it has produce the item, it releases semCon.
  • Before get( ) can consume an item, it must acquire a permit from semCon. After it consumes the item, it releases semProd.
  • This “give and take” mechanism ensures that each call to put( ) must be followed by a call to get( ).
  • Also notice that semCon is initialized with no available permits. This ensures that put( ) executes first. The ability to set the initial synchronization state is one of the more powerful aspects of a semaphore.
Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote