C++11 简单生产者消费者多线程

标签 c++ multithreading c++11

我正在尝试自学多线程,我在这里遵循了本教程:https://www.classes.cs.uchicago.edu/archive/2013/spring/12300-1/labs/lab6/

如果你一直滚动到底部,就会有一个生产者-消费者的示例片段,它要求我们解决此代码中发现的竞争条件:

#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <queue>
using namespace std;

int main() {
    int c = 0;
    bool done = false;
    queue<int> goods;

    thread producer([&]() {
        for (int i = 0; i < 500; ++i) {
            goods.push(i);
            c++;
        }

        done = true;
    });

    thread consumer([&]() {
        while (!done) {
            while (!goods.empty()) {
                goods.pop();
                c--;
            }
        }
    });

    producer.join();
    consumer.join();
    cout << "Net: " << c << endl;
}

最后的净值应该是0,这是我的尝试:

#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <queue>
#include <atomic>
using namespace std;


int main() {

    int c = 0;

    bool done = false;
    queue<int> goods;
    mutex mtx;  
    condition_variable cond_var;

    // thread to produce 500 elements
    thread producer([&]() {

        for (int i = 0; i < 500; ++i) {
            // lock critical secion
            unique_lock<mutex> lock(mtx);   

            goods.push(i);
            c++;
            lock.unlock();

            // notify consumer that data has been produced
            cond_var.notify_one();
        }

        // notify the consumer that it is done
        done = true;
        cond_var.notify_one();


    });

    // thread to consume all elements
    thread consumer([&]() {

        while (!done) {
            unique_lock<mutex> lock(mtx);   
            while (!goods.empty()) {
                goods.pop();
                c--;
            }
            // unlocks lock and wait until something in producer gets put
            cond_var.wait(lock);
        }
    });

    producer.join();
    consumer.join();
    cout << "Net: " << c << endl;
}

我觉得我从根本上错过了一些东西。我相信我遇到的最大问题是消费者使用 cond_var.wait() ,因为如果生产者将“done”设置为 true 那么消费者将不会返回到 while(!goods.empty()) 。但我不知道如何解决它。

任何提示、解释甚至不同的方法将不胜感激!

最佳答案

制作人:

thread producer([&]() {

    for (int i = 0; i < 500; ++i)
    {
        {
            // Just have a lock while interacting with shared items.
            unique_lock<mutex> lock(mtx);   
            goods.push(i);
            c++;
        }
        cond_var.notify_one();
    }

    // Lock to update shared state.
    unique_lock<mutex> lock(mtx);   
    done = true;
    cond_var.notify_one();
});

消费者

thread consumer([&]() {

    // This loop exits when
    //        done          => true
    //   AND  goods.empty() => true

    // Acquire lock before checking shared state.
    unique_lock<mutex> lock(mtx);

    while (!(done && goods.empty()))
    {
        // Wait until there is something in the queue to processes
        // releasing lock while we wait.
        // Break out if we are done or goods is not empty.
        cond_var.wait(lock, [&](){return done || !goods.empty();});

        // You now have the lock again, so modify shared state is allowed
        // But there is a possibility of no goods being available.
        // So let's check before doing work.
        if (!goods.empty())
        {
            goods.pop();
            c--;
        }
    }
});

或者,如果我们只是简单地解决竞争条件。我们可以简单地检查 done 的状态并确保没有其他变量发生交互。

制作人:

thread producer([&]() {

    // The consumer is not allowed to touch goods
    // until you are finished. So just use with
    // no locks.
    for (int i = 0; i < 500; ++i)
    {
        goods.push(i);
        c++;
    }

    // Lock to update shared state.
    // Tell consumer we are ready for processing.
    unique_lock<mutex> lock(mtx);   
    done = true;
    cond_var.notify_one();
});

消费者

thread consumer([&]() {

    // Acquire lock before checking shared state.
    unique_lock<mutex> lock(mtx);
    cond_var.wait(lock, [&](){return done;});

    // We now know the consumer has finished all updates.
    // So we can simply loop over the goods and processes them
    while (!goods.empty())
    {
        goods.pop();
        c--;
    }
});

关于C++11 简单生产者消费者多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69453363/

相关文章:

c++ - 成员函数特征

c++ - 为什么我不能转发声明 typedef?

android - OpenCV无法为ARM64目标构建(Android)

c++ - 是否可以编写一个函数,它接受具有不同初始化的模板参数

c - Linux内核与多线程用户应用同步问题

c - pthread 程序的臭名昭著的行为

multithreading - Delphi TTask 从主线程获取数据

c++ - 避免使用派生类进行 dynamic_cast (Cast Derived class)

c++ - 如何访问在 C++ 中声明数据成员的名称并将这些名称输出到控制台

c++ - 重载类方法与模板