C++11如何在1个线程中使用条件变量处理2个线程安全队列

C++11 How to handle 2 thread safe queues using condition variables in 1 thread

本文关键字:线程 变量 条件 处理 2个 队列 安全 1个 C++11      更新时间:2023-10-16

我有两个连接对象在各自的线程上运行,每个线程都将不同的数据放入在主线程中运行的相应队列中。因此,主线程有2个队列,当其中任何一个队列发出已放入数据的信号时,需要唤醒主线程。我已经编写了一个线程安全队列,它封装了theadsafe_queue中的条件变量的推送、弹出和发信号。但它似乎不起作用,因为在主循环中,它可以阻塞在第一个队列中,数据可以进入第二个队列而不会被唤醒,反之亦然
我必须在两个队列之间共享相同的条件变量和互斥对象吗。我可以修改我的threadsafe_queue,将条件变量和互斥对象作为参数,并将相同的参数传递给每个队列。或者我在想,也许可以使用wait_until和每个队列的计时器,以便在超时时有机会检查每个队列,但这似乎并不有效。主处理线程有很多带有静态对象/变量和容器的遗留代码,因此不能在不引入大量锁的情况下将其拆分为2个线程。你认为什么是最好的方法。

合并队列。

或者,写一个流媒体系统。生产者不需要知道他们的数据去了哪里;它必须走了。他们需要一个:

template<class T>
using sink=std::function<void(T)>;

发送他们的数据。

侦听器不需要知道数据来自哪里。它需要一个来源:

template<class T>
using source= sink<sink<T>>;

现在,它们在不同的线程上;所以你需要一种从a到B获取数据的方法。

template<class T>
struct threadsafe_queue {
sink<T> get_sink();
source<T> get_source();
};

在那里维护您的互斥锁、条件变量和缓冲区。

现在是有趣的部分。如果我们有X=variant<A,B>,那么sink<X>可以转换为sink<A>(source<A>也可以转换为source<X>(。

因此,如果线程1产生A,线程2产生B,那么它们都可以在不知情的情况下馈送到sink<X>中。

同时,使用者线程看到来自队列的AB

您可以将source<T>=sink<sink<T>>替换为source<T>=std::function<std::optional<T>()>,完成后返回空。我喜欢源是汇的汇;用途是:

void print_ints( source<int> src ) {
src([](int x){ std::cout<<x<<','; });
std::cout<<"n";
}

与我不太喜欢的:

void print_ints( source<int> src ) {
while(auto x=src()){std::cout<<*x<<','; };
std::cout<<"n";
}

另外,您可以标记源/汇类型并重载|和添加pipe<In,Out>等。

但这在这里没有用。