Question

In: Computer Science

Research and Program Producer-Consumer Problem In this assignment you will design a programming solution to the...

Research and Program Producer-Consumer Problem

In this assignment you will design a programming solution to the bounded-buffer problem using the producer and consumer processes shown in the lecture notes. The solution presented in the notes uses three semaphores: empty and full, which count the number of empty and full slots in the buffer, and mutex, which is a binary semaphore that protects the actual insertion or removal of items in the buffer. For this assignment, standard counting semaphores will be used for empty and full, Use a mutex lock, rather than a binary semaphore, to represent the mutex. The producer and consumer—running as separate threads will move items to and from a buffer that is synchronized with these empty, full, and mutex structures.

The buffer

Internally, the buffer will consist of a fixed-size array of type buffer item (which will be defined using typedef). The array of buffer _item objects will be manipulated as a circular queue.

The buffer will be manipulated with two functions, insert_item() and remove_item(), which are called by the producer and consumer threads, respectively.

The insert_item() and remove_item) functions will synchronize the producer and consumer using the algorithms outlined in the class lecture. The buffer will also require an initialization function that initializes the mutual exclusion object mutex along with the empty and full semaphores.

The main() function will initialize the buffer and create the separate producer and consumer threads. Once it has created the producer and consumer threads, the main() function will sleep for a period of time and upon awakening, will terminate the application. The main() function will be passed three parameters on the command line:

a.   How long to sleep before terminating

b. The number of producer threads

c. The number of consumer threads

Producer and Consumer Threads

The producer thread will alternate between sleeping for a random period of time and inserting a random integer into the buffer. Random numbers will be produced using the rand() function, which produces random integers between 0 and RAND_MAX. The consumer will also sleep for a random period of time and, upon wakening, will attempt to remove an item from the buffer.

Mutex Locks

The code should have commands to create, acquire, and release mutex locks.

Assumption: You will use the book and lecture notes for base info to complete the program. You will conduct your own research to fill in any knowledge holes.

Use POSIX Pthreads.

Solutions

Expert Solution

Take an example that a circular buffer with two pointers in and out to indicate the next available position for depositing data and the position that contains the next data to be retrieved. See the diagram below. There are two groups of threads, producers and consumers. Each producer deposits a data items into thein position and advances the pointer in, and each consumer retrieves the data item in position out and advances the pointer out.

producer will produce an item and place it in a bound-buffer for the consumer. Then the consumer will remove the item from the buffer and print it to the screen.

bound-buffer it is a container with a limit. We have to be very careful in our case that we don’t over fill the buffer or remove something that isn’t there; in c this will produce a segmentation fault.

Here is an example of how registers work when you increment a counter-

register1 = counter;

register1 = register1 + 1;

counter = register1;

Now image two threads manipulating this same example but one thread is decrementing –

(T1) register1 = counter;               [register1 = 5]

(T1) register1 = register1 + 1;       [register1 = 6]

(T2) register2 = counter;       [register2 = 5]

(T2) register2 = register2 – 1;        [register2 = 4]

(T1) counter = register1;               [counter = 6]

(T2) counter = register2;      [counter = 4]

Create the producer threads.

Create the consumer threads.

Put main() to sleep().

Exit the program.

If you are kind of rusty on how pthreads work, I have a previous tutorial that may be some help in understanding them:

Prime numbers using POSIX threads on Linux in [C]

That will give you a clearer picture on how to create a pthread.

Time for the code…

CODE:

/* buffer.h */

typedef int buffer_item;

#define BUFFER_SIZE 5

/* main.c */

#include <stdlib.h>

#include <stdio.h>

#include <pthread.h>

#include <semaphore.h>

#include "buffer.h"

#define RAND_DIVISOR 100000000

#define TRUE 1

/* The mutex lock */

pthread_mutex_t mutex;

/* the semaphores */

sem_t full, empty;

/* the buffer */

buffer_item buffer[BUFFER_SIZE];

/* buffer counter */

int counter;

pthread_t tid;    //Thread ID

pthread_attr_t attr; //Set of thread attributes

void *producer(void *param); /* the producer thread */

void *consumer(void *param); /* the consumer thread */

void initializeData() {

/* Create the mutex lock */

pthread_mutex_init(&mutex, NULL);

/* Create the full semaphore and initialize to 0 */

sem_init(&full, 0, 0);

/* Create the empty semaphore and initialize to BUFFER_SIZE */

sem_init(&empty, 0, BUFFER_SIZE);

/* Get the default attributes */

pthread_attr_init(&attr);

/* init buffer */

counter = 0;

}

/* Producer Thread */

void *producer(void *param) {

buffer_item item;

while(TRUE) {

/* sleep for a random period of time */

int rNum = rand() / RAND_DIVISOR;

sleep(rNum);

/* generate a random number */

item = rand();

/* acquire the empty lock */

sem_wait(&empty);

/* acquire the mutex lock */

pthread_mutex_lock(&mutex);

if(insert_item(item)) {

fprintf(stderr, " Producer report error condition\n");

}

else {

printf("producer produced %d\n", item);

}

/* release the mutex lock */

pthread_mutex_unlock(&mutex);

/* signal full */

sem_post(&full);

}

}

/* Consumer Thread */

void *consumer(void *param) {

buffer_item item;

while(TRUE) {

/* sleep for a random period of time */

int rNum = rand() / RAND_DIVISOR;

sleep(rNum);

/* aquire the full lock */

sem_wait(&full);

/* aquire the mutex lock */

pthread_mutex_lock(&mutex);

if(remove_item(&item)) {

fprintf(stderr, "Consumer report error condition\n");

}

else {

printf("consumer consumed %d\n", item);

}

/* release the mutex lock */

pthread_mutex_unlock(&mutex);

/* signal empty */

sem_post(&empty);

}

}

/* Add an item to the buffer */

int insert_item(buffer_item item) {

/* When the buffer is not full add the item

and increment the counter*/

if(counter < BUFFER_SIZE) {

buffer[counter] = item;

counter++;

return 0;

}

else { /* Error the buffer is full */

return -1;

}

}

/* Remove an item from the buffer */

int remove_item(buffer_item *item) {

/* When the buffer is not empty remove the item

and decrement the counter */

if(counter > 0) {

*item = buffer[(counter-1)];

counter--;

return 0;

}

else { /* Error buffer empty */

return -1;

}

}

int main(int argc, char *argv[]) {

/* Loop counter */

int i;

/* Verify the correct number of arguments were passed in */

if(argc != 4) {

fprintf(stderr, "USAGE:./main.out <INT> <INT> <INT>\n");

}

int mainSleepTime = atoi(argv[1]); /* Time in seconds for main to sleep */

int numProd = atoi(argv[2]); /* Number of producer threads */

int numCons = atoi(argv[3]); /* Number of consumer threads */

/* Initialize the app */

initializeData();

/* Create the producer threads */

for(i = 0; i < numProd; i++) {

/* Create the thread */

pthread_create(&tid,&attr,producer,NULL);

}

/* Create the consumer threads */

for(i = 0; i < numCons; i++) {

/* Create the thread */

pthread_create(&tid,&attr,consumer,NULL);

}

/* Sleep for the specified amount of time in milliseconds */

sleep(mainSleepTime);

/* Exit the program */

printf("Exit the program\n");

exit(0);

}

Here, we have the output for the program. As you can see we told main to quit after 10 seconds and we produced 10 producer and 10 consumer threads.

You can try this also

#include <iostream>



#include "ProducerConsumer.h"



// static data variable

static int Buffer[BUFFER_SIZE]; // the buffer

static int In = 0;       // next empty slot in the buffer

static int Out = 0;                             // next available data slot



static Semaphore NotFull("NotFull", BUFFER_SIZE);

static Semaphore NotEmpty("NotEmpty", 0);

static Semaphore BufferLock("BufferLock", 1);   // lock protecting the buffer



strstream *Filler(int n)

{

  int i;

  strstream *Space;



  Space = new strstream;

  for (i = 0; i < n; i++)

     (*Space) << ' ';

  (*Space) << '\0';

  return Space;

}



ProducerThread::ProducerThread(int No, int numberofdata)

            : Number(No), NumberOfData(numberofdata)

{

  ThreadName.seekp(0, ios::beg);

  ThreadName << "Producer" << No << '\0';

};



/ConsumerThread::ConsumerThread(int No)

            : Number(No)

{

  ThreadName.seekp(0, ios::beg);

  ThreadName << "Consumer" << No << '\0';

}



void ProducerThread::ThreadFunc()

{

  Thread::ThreadFunc();

  int data;

  strstream *Space;



  Space=Filler(4);

  for (int i = 1; i <= NumberOfData; i++) {

       Delay();

       NotFull.Wait();     // wait until the buffer has space

       BufferLock.Wait();       // lock the buffer

       data = rand() % 100 + 1000 * Number; // generate data

       Buffer[In] = data;       // add data to the buffer

       cout << Space->str() << ThreadName.str() << " deposited "

            << data << " to the buffer" << endl;

       In = (In + 1) % BUFFER_SIZE;    // advance input pointer

       BufferLock.Signal();     // release the buffer

       NotEmpty.Signal(); // buffer is not full now

  }



  Delay();                      // about to add END

  NotFull.Wait();               // wait until the buffer has space

  BufferLock.Wait();            // lock the buffer

  Buffer[In] = END;             // put the END message in

  cout << Space->str() << ThreadName.str()

       << " deposited END and Exit" << endl;

  In = (In + 1) % BUFFER_SIZE; // advance in pointer

  BufferLock.Signal();          // release the buffer

  NotEmpty.Signal();            // buffer is not full

  Exit();

}



void ConsumerThread::ThreadFunc()

{

  Thread::ThreadFunc();

  int data = 0 ;

  strstream *Space;



  Space=Filler(2);

  while (true) {

       Delay();

       NotEmpty.Wait();              // wait until the buffer has data

       BufferLock.Wait();            // lock the buffer

       data = Buffer[Out];           // get a data item from the buffer

       if (data != END) {            // If it is not "END"

            cout << Space->str() << ThreadName.str()<< " received "

                 << data << " from the buffer" << endl;

            Out = (Out + 1) % BUFFER_SIZE; // advance buffer pointer

            BufferLock.Signal();            // unlock the buffer

            NotFull.Signal();        // buffer is not full

       }

       else {

            cout << Space->str() << ThreadName.str()

                 << " received END and exits" << endl;

            Out = (Out + 1) % BUFFER_SIZE;

            BufferLock.Signal();

            NotFull.Signal();

            break;

     }

}

Exit();

}



Related Solutions

Implement the Producer-Consumer Problem programming assignment at the end of Chapter 5 in the textbook using...
Implement the Producer-Consumer Problem programming assignment at the end of Chapter 5 in the textbook using the programming language Java instead of the described C code. You must use Java with Threads instead of Pthreads.A brief overview is below. This program should work as follows: The user will enter on the command line the sleep time, number of producer threads, and the number of consumer threads. One example of the Java application from the command line could be “java ProducerConsumer...
Below is an attempt to solve the producer-consumer problem. Is this a correct solution? If yes,...
Below is an attempt to solve the producer-consumer problem. Is this a correct solution? If yes, what is achieved and how? If not, what is the problem? Explain your answer in either case. (Note: Assume no syntax or compilation errors. You’re asked about the concurrency logic/correctness and the use of semaphores for this.) #define N 100                 /* number of slots in the buffer */ semaphore mutex = 1;          /* controls access to critical */ semaphore empty = N;          /* counts...
Please do this in java program. In this assignment you are required to implement the Producer...
Please do this in java program. In this assignment you are required to implement the Producer Consumer Problem . Assume that there is only one Producer and there is only one Consumer. 1. The problem you will be solving is the bounded-buffer producer-consumer problem. You are required to implement this assignment in Java This buffer can hold a fixed number of items. This buffer needs to be a first-in first-out (FIFO) buffer. You should implement this as a Circular Buffer...
The bounded buffer problem is a producer-consumer problem where a producer process adds new items to...
The bounded buffer problem is a producer-consumer problem where a producer process adds new items to a shared buffer and a consumer process consumes items from that buffer (in the first-in-first-out (FIFO) order). When a producer adds a new item, the buffer size grows by one, and whenever a consumer consumes an item from the buffer, the size is reduced by one. The producer process must wait when the buffer is full likewise the consumer process must wait when the...
Assignment 1 – Writing a Linux Utility Program Instructions For this programming assignment you are going...
Assignment 1 – Writing a Linux Utility Program Instructions For this programming assignment you are going to implement a simple C version of the UNIX cat program called lolcat. The cat program allows you to display the contents of one or more text files. The lolcat program will only display one file. The correct usage of your program should be to execute it on the command line with a single command line argument consisting of the name you want to...
A) Describe and explain in detail the producer-consumer principle for concurrent programming as we studied in...
A) Describe and explain in detail the producer-consumer principle for concurrent programming as we studied in this course B) Choose one of the mechanisms we use studied to synchronize the producer and consumer threads and write and example demonstrator (5pts) C) Explain in your comments in the Java code the most important aspects that enabled synchronization between the the 2 threads in (ii) above. (5pts)
PROGRAMMING LANGUAGE : JAVA Problem specification. In this assignment, you will create a simulation for a...
PROGRAMMING LANGUAGE : JAVA Problem specification. In this assignment, you will create a simulation for a CPU scheduler. The number of CPU’s and the list of processes and their info will be read from a text file. The output, of your simulator will display the execution of the processes on the different available CPU’s. The simulator should also display: -   The given info of each process -   CPU utilization - The average wait time - Turnaround time for each process...
Programming Problem Design a program in java that can perform three different arithmetic operations based on...
Programming Problem Design a program in java that can perform three different arithmetic operations based on the user’s input. The three operations are 1. Summation of integers from 1 to m 2. Factorial of a given number n (n!) 3. Finding the leftmost digit of a given integer (note: you have to use int) This program should prompt the user a menu including four options, ask the user for one option, and perform the corresponding computation. This process will repeat...
C PROGRAMMING – Steganography In this assignment, you will write an C program that includes processing...
C PROGRAMMING – Steganography In this assignment, you will write an C program that includes processing input, using control structures, and bitwise operations. The input for your program will be a text file containing a large amount of English. Your program must extract the “secret message” from the input file. The message is hidden inside the file using the following scheme. The message is hidden in binary notation, as a sequence of 0’s and 1’s. Each block of 8-bits is...
In this programming assignment, you will implement a SimpleWebGet program for non- interactive download of files...
In this programming assignment, you will implement a SimpleWebGet program for non- interactive download of files from the Internet. This program is very similar to wget utility in Unix/Linux environment.The synopsis of SimpleWebGet is: java SimpleWebGet URL. The URL could be either a valid link on the Internet, e.g., www.asu.edu/index.html, or gaia.cs.umass.edu/wireshark-labs/alice.txt or an invalid link, e.g., www.asu.edu/inde.html. ww.asu.edu/inde.html. The output of SimpleWebGet for valid links should be the same as wget utility in Linux, except the progress line highlighted...
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT