C++20 生产者消费者例子

template<typename T>
class BlockQueue {
public:
    BlockQueue(int cap) : cap_(cap) {

    }

    void put(const T &element) {
        unique_lock<mutex> lock_(mutex_);

        while (data_.size() == cap_) {
            writeCond.wait(lock_);
        }

        data_.push(element);
        readCond.notify_all();
    }

    T get() {
        unique_lock<mutex> lock_(mutex_);

        while (data_.empty()) {
            readCond.wait(lock_);
        }

        T element = data_.front();
        data_.pop();
        writeCond.notify_all();
        return element;
    }

private:
    int cap_;
    queue<T> data_;
    mutex mutex_;
    condition_variable readCond;
    condition_variable writeCond;
};


template<typename T>
class ProduceConsume {
private:
    BlockQueue<T> blockQueue;
    mutex outPutMutex;
public:
    ProduceConsume(int buffSize) : blockQueue(buffSize) {
    }

    void produce() {
        for (int i = 0; i < 5; ++i) {
            auto element = rand();
            blockQueue.put(element);
            {
                lock_guard<mutex> outPutLock(outPutMutex);
                cout << "thread " << this_thread::get_id() << " put " << element << endl;
            }
            sleep(1);
        }
    }

    void consume() {
        for (int i = 0; i < 5; ++i) {
            auto element = blockQueue.get();
            {
                lock_guard<mutex> outPutLock(outPutMutex);
                cout << "thread " << this_thread::get_id() << " get " << element << endl;
            }
            sleep(1);
        }
    }
};

int main() {
    {
        ProduceConsume<int> produceConsume(3);
        jthread produce(&ProduceConsume<int>::produce, std::ref(produceConsume));
        jthread consume(&ProduceConsume<int>::consume, std::ref(produceConsume));

        sleep(3);

        cout << "main thread continue in jthread life scope..." << endl;
    }
    cout << "main thread continue out jthread life scope" << endl;
}

输出:

thread 140402881443584 put 1804289383
thread 140402881443584 put 846930886
thread 140402881443584 put 1681692777
main thread continue in jthread life scope...
thread 140402881443584 put 1714636915
thread 140402873050880 get 1804289383
thread 140402873050880 get 846930886
thread 140402873050880 get 1681692777
thread 140402873050880 get 1714636915
thread 140402873050880 get 1957747793
thread 140402881443584 put 1957747793
main thread continue out jthread life scope

问题:

(1) 代码使用了两把锁,会造成死锁吗

答案:不会。因为output锁是在blockqueue内部的锁释放之后,才使用的。不构成循环依赖

(2) 为何启动线程时:类的成员函数需要传地址,对象实例要传引用

答案:C++标准要求

(3) 为何jthread 没有Join,但主线程并未退出?

jthread对象在作用域快要结束时,会自动析构,在jthread的析构函数中调用了join。让他自己阻塞

直到jthread的任务函数执行完成之后,解除阻塞。主函数继续运行 (从程序的输出中也可以观察到这一点)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值