std::condition_variable 是 C++11 标准引入的,用于实现线程间的同步,用于线程实现带有条件的去竞争锁的问题。
当我们使用互斥锁时,多个线程只要发现锁空闲,就会去抢锁,争夺执行权限。如果抢到锁的线程没有满足某个条件,它就不具备执行权限,浪费系统资源。所以,我们希望线程在满足某个条件时,再去抢锁。
条件变量能够为互斥锁构建一个条件,当线程去争抢该锁时,必须满足相应的条件。如果不满足条件,则进入阻塞等待。当条件满足时,再被唤醒。
1. 问题场景
#if 1
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<thread>
#include<queue>
#include<mutex>
#include<chrono>
const size_t buffer_size = 5;
std::queue<size_t> buffer;
std::mutex buffer_mutex;
void do_produce()
{
size_t index = 0;
while (true)
{
buffer_mutex.lock();
if (buffer.size() < buffer_size)
{
std::cout << buffer.size() << " " << std::this_thread::get_id() << " 生产:" << index << std::endl;
buffer.push(index++);
}
buffer_mutex.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(300));
}
}
void do_consume()
{
while (true)
{
buffer_mutex.lock();
if (buffer.size() > 0)
{
size_t element = buffer.front();
std::cout << std::this_thread::get_id() << " 消费:" << element << std::endl;
buffer.pop();
}
buffer_mutex.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
}
// 不足
// 生产者和消费者都在每次操作前都尝试获取锁,这可能会导致频繁的上下文切换和锁竞争,降低程序的性能,特别是在多线程环境下
void test()
{
std::thread producer(do_produce);
std::thread consumer1(do_consume);
std::thread consumer2(do_consume);
producer.join();
consumer1.join();
consumer2.join();
}
int main()
{
test();
return EXIT_SUCCESS;
}
#endif
2. 问题解决
#if 0
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<thread>
#include<queue>
#include<mutex>
#include<chrono>
// 条件变量
std::condition_variable producer_condition;
std::condition_variable consumer_condition;
std::queue<int> buffer;
std::mutex buffer_mutex;
void do_produce()
{
int index = 0;
while (true)
{
{
std::unique_lock<std::mutex> lock(buffer_mutex);
producer_condition.wait(lock, [&]() {return buffer.size() < 5; });
std::cout << std::this_thread::get_id() << " 生产:" << index << std::endl;
buffer.push(index++);
std::this_thread::sleep_for(std::chrono::milliseconds(300));
}
consumer_condition.notify_all();
}
}
void do_consume()
{
while (true)
{
{
std::unique_lock<std::mutex> lock(buffer_mutex);
consumer_condition.wait(lock, [&]() {return !buffer.empty(); });
int element = buffer.front();
buffer.pop();
std::cout << std::this_thread::get_id() << " 消费:" << element << ", 剩余:" << buffer.size() << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
producer_condition.notify_one();
}
}
void test()
{
std::thread producer(do_produce);
std::thread consumer1(do_consume);
std::thread consumer2(do_consume);
producer.join();
consumer1.join();
consumer2.join();
}
int main()
{
test();
return EXIT_SUCCESS;
}
#endif

冀公网安备13050302001966号