【问题标题】:One thread waiting for multiple thread events一个线程等待多个线程事件
【发布时间】:2020-10-04 21:24:00
【问题描述】:

我有一个线程在等待来自不同数量的其他线程的某个事件,这取决于来自这个线程的事件来继续处理。如何编码以避免忙循环?

更具体地说,我有多个线程来处理它们各自的视频帧并将其写入屏幕缓冲区(在不同的位置)。全部完成后,一个线程发送缓冲区进行绘制,然后这些线程等待绘制调用完成,然后继续进行下一帧。

这需要在 C++ 中实现。使用的 C++ 标准不受限制。

编辑:std::condition_variable 似乎不是解决方案。由于它需要一个互斥体,并且线程(互斥体)的数量在运行时是已知的,我无法将互斥体放入std::vector

我的程序的伪代码是这样的:

drawThread:
    loop:
        for each processThread:
            wait for event
        draw()

processThread:
    loop:
        process()
        notify drawThread
        wait for draw to finish

编辑:我尝试了什么:

std::vector<std::atomic_bool> ready_flags;
std::atomic_bool finished_drawing = false;
void drawThread()
{
    while(true)
    { 
        CHECK:
        for(auto& flag: ready_flags)
        {
            if(!flag)
                goto CHECK;
        }
        draw();
        finished_drawing = true;
    }
}
void ProcessThread(int id)
{
    while(true)
    {
        process();
        finished_drawing=false;
        ready_flags[id] = true;
        while(!finished_drawing)
            ;
    }
}

【问题讨论】:

  • 条件变量只需要一个互斥锁。没有法律规定每个线程必须始终使用自己的独占互斥锁。这样做实际上违背了互斥锁的目的,因为它们被明确设计为可由多个线程访问。毕竟,这就是互斥锁的全部意义所在。
  • 互斥锁保护数据免受来自任意数量线程的并发访问。也就是说,您已经选择了工具(线程数、通信方法),现在您遇到了问题。但是,也许您更应该描述目标,另请参阅“XY 问题”。
  • 你说你不能使用互斥体向量。其实you can,只是你需要通过适当的reserve来避免重新分配。或者,如果您事先不知道线程/互斥体的数量,您可以使用互斥体的std::dequestd::list 来代替。问题可能是,您不能一次等待多个条件变量。但是这个问题是可以解决的,例如,通过引入一些伴随单个条件变量的(无锁)事件队列。
  • @DanielLangr 你能根据我的情况详细说明一下吗?即使只是伪代码也值得赞赏。

标签: c++ multithreading


【解决方案1】:

我想出了一个可行的解决方案

const int processThreadCount;
std::atomic<int> ready_count{};
std::shared_mutex drawing_mutex;
std::conditional_variable_any can_draw;
void drawThread()
{
    while(true)
    { 
        std::unique_lock lk{drawing_mutex};
        canDraw.wait(lk, [&]{return ready_count==processThreadCount;};
        draw();
        ready_count=0;
    }
}
void ProcessThread(int id)
{
    while(true)
    {
        std::shared_lock lk{drawing_mutex};
        process();
        ++ready_count;
        can_draw.notify_one();
    }
}

【讨论】:

    猜你喜欢
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    • 2015-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多