消费者线程等待生产者发来的信息
第一版 while + sleep
while (true)
{
if (is_sent_)
{
is_sent_ = false;
//Do something ...
}
// Sleep this thread for 5 MilliSeconds
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
总感觉sleep是很傻的行为,sleep(0) 还是sleep(10) ?貌似window平台最小精度为15ms
改进的方案 ,用C++ 11的condition_variable
#include <queue>
#include <thread>
#include <iostream>
#include <mutex>
#include <condition_variable>
std::queue<int> dataQueue;
std::mutex queueMutex;
std::condition_variable queueConditionVariable;
void producerFunction() {
// This function will keep generating data forever
int sleepSeconds;
int newNumber;
while (true) {
// Wait from 1 to 3 seconds before generating data
sleepSeconds = rand() % 3 + 1;
std::this_thread::sleep_for(std::chrono::seconds(sleepSeconds));
// Add a number to the queue
newNumber = rand() % 100 + 1; // Random number from 1 to 100
std::lock_guard<std::mutex> g(queueMutex);
dataQueue.push(newNumber);
std::cout << "Added number to queue: " << newNumber << std::endl;
// Notify one thread that the condition variable might have changed. Notice
// the notification is sent while still holding the lock
queueConditionVariable.notify_one();
}
}
void consumerFunction() {
// This function will consume data forever
while (true) {
int numberToProcess = 0;
// We only need to lock the mutex for the time it takes us to pop an item
// out. Adding this scope releases the lock right after we poped the item
{
// Condition variables need a unique_lock instead of a lock_guard because
// the mutex might be locked and unlocked multiple times. Creating the
// unique_lock like this, locks the mutex
std::unique_lock<std::mutex> g(queueMutex);
// This call to `wait` will first check if the contion is met. i.e. If
// the queue is not empty.
// If the queue is not empty, the execution of the code will continue
// If the queue is empty, it will unlock the mutex and wait until a signal
// is sent to the condition variable. When the signal is sent, it will
// acquire the lock and check the condition again.
queueConditionVariable.wait(g, [] { return !dataQueue.empty(); });
// We don't need to check if the queue is empty anymore, because the
// Condition Variable does that for us
numberToProcess = dataQueue.front();
dataQueue.pop();
}
// Only process if there are numbers
if (numberToProcess) {
std::cout << "Processing number: " << numberToProcess << std::endl;
}
}
}
int main() {
std::thread producer(producerFunction);
std::thread consumer1(consumerFunction);
producer.join();
consumer1.join();
}
运行结果:
root@ubuntu:/app/boost/example/condition# g++ condition.cpp -o condition -lpthread
root@ubuntu:/app/boost/example/condition# ./condition
Added number to queue: 87
Processing number: 87
Added number to queue: 16
Processing number: 16
Added number to queue: 36
Processing number: 36
Added number to queue: 93
Processing number: 93
Added number to queue: 22
Processing number: 22
Added number to queue: 28
Processing number: 28