Used mutex
and condition_variable
. While using them, I utilized unique_lock
class that provides a flexible way to lock/unlock mutexes and control condition variables.
#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <cstdlib>
#include <unistd.h>
#define MAX_SIZE 4
using namespace std;
queue<int> q;
condition_variable cv;
mutex mu;
void producer(int n) {
for (int i = 0; i < n; ++i) {
unique_lock<mutex> lock(mu);
cv.wait(lock, []{return q.size() < MAX_SIZE;});
q.push(i);
cout << "Produced: " << i;
cout << " Queue Size: " << q.size() << endl;
cv.notify_one();
lock.unlock();
sleep(rand() % 3);
}
}
void consumer(int n) {
for (int i = 0; i < n; ++i) {
unique_lock<mutex> lock(mu);
cv.wait(lock, []{return !q.empty();});
int value = q.front();
q.pop();
cout << "Consumed: " << i;
cout << " Queue Size: " << q.size() << endl;
cv.notify_one();
lock.unlock();
sleep(rand() % 5);
}
}
int main() {
thread producer_thread(producer, 20);
thread consumer_thread(consumer, 20);
producer_thread.join();
consumer_thread.join();
}
You might want to use lock_guard
class that is less flexible but provides more structured and safer way to lock/unlock a mutex. It locks the mutex on construction and unlocks it on destruction.
Comments