热线电话:0755-23712116
邮箱:contact@shuangyi-tech.com
地址:深圳市宝安区沙井街道后亭茅洲山工业园工业大厦全至科技创新园科创大厦2层2A
0 前言
1 消费者“被动等待”
#include
#include
#include
static std::mutex mtx;
static std::deque<int> dq;
static int productNum = 5;
void Producer()
{
using namespace std::literals::chrono_literals;
for (int i = 1; i <= productNum; ++i) {
mtx.lock();
dq.push_front(i);
std::cout << "Producer 生产产品为: " << i << std::endl;
mtx.unlock();
// std::this_thread::sleep_for(1s);
}
}
void Consumer()
{
while (true) {
if (dq.empty()) {
continue;
}
mtx.lock();
int data = dq.back();
dq.pop_back();
std::cout << "Consumer 消费产品为: " << data << std::endl;
mtx.unlock();
}
}
int main()
{
std::thread t1(Producer);
std::thread t2(Consumer);
t2.join();
t1.join();
std::cin.get();
}
程序运行结果如下:
如果让生产者线程每生产一个产品后休息(sleep) 1s,结果如下:
解释:该例子中,生产者和消费者分别对应两个线程。队列中存在物品时,消费者去消费,否则空循环,一直等待。
缺点:当双端队列中没有物品时,消费者只会原地死等,不会去催。
2 消费者“主动出击”
#include
#include
#include
#include
#include
std::mutex mtx;
std::condition_variable cv;
std::vector<int> vec;
int productNum = 5;
void Producer()
{
for (int i = 1; i <= productNum; ++i) {
std::unique_lock<std::mutex> lock(mtx);
while (!vec.empty()) {
cv.wait(lock); // vec 不为空时阻塞当前线程
}
vec.push_back(i);
std::cout << "Producer生产产品: " << i << std::endl;
cv.notify_all(); // 释放线程锁
}
}
void Consumer()
{
while (true) {
std::unique_lock<std::mutex> lock(mtx);
while (vec.empty()) {
cv.wait(lock); // vec 为空时等待线程锁。其他线程锁释放时,当前线程继续执行
}
int data = vec.back();
vec.pop_back();
std::cout << "Consumer消费产品: " << data << std::endl;
cv.notify_all();
}
}
int main()
{
std::thread t1(Producer);
std::thread t2(Consumer);
t2.join();
t1.join();
std::cin.get();
}
程序运行结果如下:
解释:该例子中,生产者和消费者分别对应两个线程。只要 vector 中存在物品时,生产者线程就阻塞,通知消费者线程去消费;vector 中不存在物品时,消费者线程阻塞,通知生产者去生产。
3 线程加入方式 join 和 detach
join:采用 join 方式,t1、t2 乱序执行,且外层主线程会等到 t1、t2 都结束了再继续执行后面的代码。
detach:如果采用 detach 方式,t1、t2 乱序执行,且脱离了外层主线程。外层主线程执行结束时,t1、t2 可能还没结束,但此时程序就退出了。
如涉及侵权,请相关权利人与我司联系删除