首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在C++中线程中有一个with循环的条件变量

在C++中线程中有一个with循环的条件变量
EN

Stack Overflow用户
提问于 2019-07-17 11:41:11
回答 2查看 4.6K关注 0票数 0

我试图弄清楚如何在std::condition_variable中使用C++实现一个“奇怪”的生产者和消费者程序,在这个程序中,我对count变量设置了一个限制。

主线程(“生产者”)增加计数,必须等待此值返回为零才能发出新的增量。

其他线程进入一个循环,它们必须减少计数器并发出通知。

我被阻塞了,因为我不清楚如何通过在所有线程的函数中有序地退出while循环来结束程序。

有人能给我一些关于如何实施它的指导吗?

代码

代码语言:javascript
运行
复制
#include <iostream>

#include <thread>
#include <condition_variable>
#include <vector>

int main() {
        int n_core = std::thread::hardware_concurrency();
    std::vector<std::thread> workers;
    int max = 100;
    int count = 0;
    std::condition_variable cv;
    std::mutex mutex;
    int timecalled = 0;


    for (int i = 0; i < n_core; i++) {
        workers.emplace_back(std::thread{[&max, &count, &mutex, &cv]() {
            while (true) {
                std::unique_lock<std::mutex> lk{mutex};
                std::cout << std::this_thread::get_id() << " cv" << std::endl;
                cv.wait(lk, [&count]() { return count == 1; });
                std::cout << std::this_thread::get_id() << " - " << count << std::endl;
                count--;
                std::cout << std::this_thread::get_id() << " notify dec" << std::endl;
                cv.notify_all();
            }
        }});
    }

    while (max > 0) {
        std::unique_lock<std::mutex> lk{mutex};
        std::cout << std::this_thread::get_id() << " cv" << std::endl;
        cv.wait(lk, [&count]() { return count == 0; });
        std::cout << std::this_thread::get_id() << " created token" << std::endl;
        count++;
        max--;
        timecalled++;
        std::cout << std::this_thread::get_id() << " notify inc" << std::endl;

        cv.notify_all();
    }

    for (auto &w : workers) {
        w.join();
    }

    std::cout << timecalled << std::endl; // must be equal to max
    std::cout << count << std::endl; // must be zero

}

问题

程序不会结束,因为它被某些最终的join卡住了。

预期结果

预期结果必须是:

代码语言:javascript
运行
复制
100
0

编辑

编辑1:我用true替换了true中的max > 0。现在循环是无界的,但是使用@prog的解决方案似乎是可行的。

编辑2:我最后添加了一个变量来检查结果。

编辑3:我将while(true)更改为while(max >0)。这会不会是并发中的一个问题,因为我们是在没有锁的情况下阅读它呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-07-17 11:58:22

线程正在等待调用cv.wait()中的新内容。

但是使用提供的lambda闭包可以观察到的唯一变化是count的值。

也必须检查max的值,以便有机会离开这个cv.wait()调用。

您的代码中的最小更改可能是

代码语言:javascript
运行
复制
cv.wait(lk, [&max, &count]() { return count == 1 || max<=0; });
if(max<=0) break;

假设对max的更改总是在互斥体的控制下发生。

用于澄清对max__的访问的编辑。

如果线程运行的循环现在是while(true),那么max变量只能在它的正文中读取,这是由mutex同步的(多亏了lk)。

主程序运行的循环是while (max > 0)max在这里读取时没有同步,但是唯一可以改变这个变量的线程是主程序本身,所以从这个角度来看,它是纯串行代码。

这个循环的整个部分由mutex同步(多亏了lk),因此在这里更改max的值是安全的,因为线程中的读操作是以相同的方式同步的。

票数 1
EN

Stack Overflow用户

发布于 2019-07-17 12:01:43

  1. 您有竞争条件:在您的代码中,max可以由多个线程读取,而在main中正在修改它,这是一种根据C++标准的竞争条件。
  2. 您在wait中使用的谓词似乎不正确(您使用的是==)。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57074998

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档