86194

Need help in implementing the Producer-Consumer problem with pthread and semaphore

Question:

I am trying to implement the Producer and Consumer problem in C++ using pthread and semaphore. I have one Producer and two consumers. My producer reads a string from a file and stores it in a queue character by character. The consumers read from the string and store in a char character also one by one. The problem is that only one of my Consumer is reading from the queue, other is not and its array is remaining empty. How do I fix this problem. Here is my program:

#include<iostream> #include<pthread.h> #include<fstream> #include<unistd.h> #include<semaphore.h> #include<queue> // define queue size #define QUEUE_SIZE 5 // declare and initialize semaphore and read/write counter static sem_t mutex,mutex1; //static int counter = 0; // Queue for saving characters static std::queue<char> charQueue; // indicator for end of file static bool endOfFile = false; // save arrays static char consumerArray1[100]; static char consumerArray2[100]; void *Producer(void *ptr) { int i=0; std::ifstream input("string.txt"); char temp; while(input>>temp) { sem_wait(&mutex); charQueue.push(temp); sem_post(&mutex1); sem_post(&mutex); //counter++; std::cout<<"Procuder Index: "<<i<<std::endl; i++; sleep(6); } endOfFile = true; pthread_exit(NULL); } void *Consumer1(void *ptr) { std::cout<<"Entered consumer 1:"<<std::endl; int i = 0; sem_wait(&mutex1); //while(charQueue.empty()); sem_post(&mutex1); while(!endOfFile)// || !charQueue.empty()) { sem_wait(&mutex1); sem_wait(&mutex); std::cout<<"Consumer1 index:"<<i<<" char: "<<charQueue.front()<<std::endl; consumerArray1[i] = charQueue.front(); charQueue.pop(); //std::cout<<charQueue.size()<<std::endl; sem_post(&mutex1); i++; //counter--; sem_post(&mutex); sleep(2); } consumerArray1[i] = '\0'; pthread_exit(NULL); } void *Consumer2(void *ptr) { std::cout<<"Entered consumer 2:"<<std::endl; int i = 0; sem_wait(&mutex1); //while(charQueue.empty()); sem_post(&mutex1); while(!endOfFile)// || charQueue.empty()) { sem_wait(&mutex1); sem_wait(&mutex); std::cout<<"Consumer2 index: "<<i<<" char: "<<charQueue.front()<<std::endl; consumerArray2[i] = charQueue.front(); charQueue.pop(); sem_post(&mutex1); i++; //counter--; sem_post(&mutex); sleep(4); } consumerArray2[i] = '\0'; pthread_exit(NULL); } int main() { pthread_t thread[3]; sem_init(&mutex,0,1); sem_init(&mutex1,0,1); pthread_create(&thread[0],NULL,Producer,NULL); int rc = pthread_create(&thread[1],NULL,Consumer1,NULL); if(rc) { std::cout<<"Thread not created"<<std::endl; } pthread_create(&thread[2],NULL,Consumer2,NULL); pthread_join(thread[0],NULL);pthread_join(thread[1],NULL);pthread_join(thread[2],NULL); std::cout<<"First array: "<<consumerArray1<<std::endl; std::cout<<"Second array: "<<consumerArray2<<std::endl; sem_destroy(&mutex); sem_destroy(&mutex1); pthread_exit(NULL); }

Edit: I added semaphore around the access of charQueue.empty() and charQueue.push() as well, but no change in output. what else should I do?

Answer1:

You have the same problem that you had before. Your Consumer1 function can call charQueue.empty while your Producer function can be calling charQueue.push(temp);. You may not access an object in one thread while another thread is, or might be, modifying it. You either need to protect charQueue with a mutex, with a semaphore, or with some other form of synchronization primitive.

Again, the compiler is free to optimize code like this:

while(charQueue.empty());

To code like this:

if (charQueue.empty()) while (1);

Why? Because your code may be accessing charQueue at any time. And it is expressly prohibited for one thread to modify an object while another thread may be accessing it. Therefore, the compiler is permitted to assume that charQueue will not be modified while this loop is executing and so there is no need to check it for emptiness more than once.

You have sempahores. Use them to ensure that only one thread might touch charQueue at a time.

Answer2:

Using guidelines from @DavidSchwartz I made this code that is working. Please suggest me a better way to implement it, as in if there are better and safer ways to do the things I have done. Sorry for me not getting most of the comments and answer as this is my first code using pthreads and semaphore. So, please bear with me:

#include<iostream> #include<pthread.h> #include<fstream> #include<unistd.h> #include<semaphore.h> #include<queue> // define queue size #define QUEUE_SIZE 5 // declare and initialize semaphore and read/write counter static sem_t mutex,mutex1; //static int counter = 0; // Queue for saving characters static std::queue<char> charQueue; // indicator for end of file static bool endOfFile = false; // save arrays static char consumerArray1[100]; static char consumerArray2[100]; void *Producer(void *ptr) { int i=0; std::ifstream input("string.txt"); char temp; while(input>>temp) { sem_wait(&mutex); charQueue.push(temp); sem_post(&mutex1); sem_post(&mutex); i++; sleep(6); } endOfFile = true; sem_post(&mutex1); pthread_exit(NULL); } void *Consumer1(void *ptr) { int i = 0; sem_wait(&mutex1); bool loopCond = endOfFile; while(!loopCond) { if(endOfFile) { loopCond = charQueue.empty(); std::cout<<loopCond<<std::endl; sem_post(&mutex1); } sem_wait(&mutex1); sem_wait(&mutex); if(!charQueue.empty()) { consumerArray1[i] = charQueue.front(); charQueue.pop(); i++; } if(charQueue.empty()&&endOfFile) { sem_post(&mutex); sem_post(&mutex1); break; } sem_post(&mutex); sleep(2); } consumerArray1[i] = '\0'; pthread_exit(NULL); } void *Consumer2(void *ptr) { int i = 0; sem_wait(&mutex1); bool loopCond = endOfFile; while(!loopCond) { if(endOfFile) { loopCond = charQueue.empty(); std::cout<<loopCond<<std::endl; sem_post(&mutex1); } sem_wait(&mutex1); sem_wait(&mutex); if(!charQueue.empty()) { consumerArray2[i] = charQueue.front(); charQueue.pop(); i++; } if(charQueue.empty()&& endOfFile) { sem_post(&mutex); sem_post(&mutex1); break; } sem_post(&mutex); sleep(4); } consumerArray2[i] = '\0'; pthread_exit(NULL); } int main() { pthread_t thread[3]; sem_init(&mutex,0,1); sem_init(&mutex1,0,1); pthread_create(&thread[0],NULL,Producer,NULL); int rc = pthread_create(&thread[1],NULL,Consumer1,NULL); if(rc) { std::cout<<"Thread not created"<<std::endl; } pthread_create(&thread[2],NULL,Consumer2,NULL); pthread_join(thread[0],NULL);pthread_join(thread[1],NULL);pthread_join(thread[2],NULL); std::cout<<"First array: "<<consumerArray1<<std::endl; std::cout<<"Second array: "<<consumerArray2<<std::endl; sem_destroy(&mutex); sem_destroy(&mutex1); pthread_exit(NULL); }

Recommend

  • Pass variables as parameters to plot_ly function
  • scrollWidth/scrollHeight give invalid dimensions
  • BizTalk - Flat file with Header multiple records and Footer - Disassemble problem
  • How do you get the selected text of a WPF FlowDocument?
  • Image rotation via itext pdf library
  • How to access Google Search “I'm Feeling Lucky” functionality using API?
  • MSVC C4100: 'application' : unreferenced formal parameter warning
  • Margin doesn't work? Need space between two elements
  • How do I align the button to the bottom of the row/column in bootstrap?
  • 'An undeclared property' when trying to create record via Web API
  • Difference between a DateTime object I create and DateTime.Now
  • Lifetime of references in STD collections
  • How does the C == operator decide whether or not two floating point values are equal?
  • Currently connected bluetooth device android
  • Can you block a website from being in a browser's history?
  • Swift: How to get string values of days, months and year from a date picker?
  • How to connect Android Studio with SQL Server database
  • Wordpress PHP within PHP
  • Why doesn't if(cell == nil) work?
  • How can I upload files to firebase's cloud storage with a path using the admin sdk?
  • Running web application developed using .NET 4.5 on Windows Xp clients
  • How to add a Contact in Contact using iPhone Native UI
  • Why do we have to put an asterisk on method parameter types in Objective-C?
  • How to set current cell on SAP GUIContainerShell in C#?
  • Various issues installing igraph in Visual Studio 2010 and Cygwin/MinGW (“sys/time.h not found”)
  • How to recreate a virtual env in python
  • R Multiple Regression Loop and Extract Coefficients
  • WooCommerce, how to remove downloadable products permission for order
  • How to handle extraction of double type numbers from a complex input (string) [duplicate]
  • Antialiasing on OpenGL ES 2.0
  • GCD implementation on a UITableView
  • Unreadable characters displaying in ASP.NET MVC
  • How to implement 'if' in Gherkin
  • Lazy Evaluation - Space Leak
  • How to populate a Mutation for a different Cassandra table in a trigger
  • Angular not getting response when it's a non-200
  • How to attach a file (pdf, jpg, etc) in a SOAP POST request?
  • Covert RFC3339 DateTime to Date in java [duplicate]
  • Bootstrap 3 Validation
  • Multiple table join MySQL multiple foreign keys