c++线程异步同时运行

Posted

技术标签:

【中文标题】c++线程异步同时运行【英文标题】:c++ thread asynchronous running simultaneously 【发布时间】:2014-05-19 00:18:05 【问题描述】:

我是 C++ 11 线程的新手。我有两个线程,我想让它们同时启动。我可以想到两种方法(如下所示)。但是,似乎它们都没有像我预期的那样工作。他们在启动另一个线程之前启动一个线程。任何提示将不胜感激!另一个问题是我正在处理线程队列。所以我会有两个消费者和四个生产者。下面的消费者代码是正确的方法吗?有没有人可以提供的参考资料?

for(int i = 1; i <= 2; i++)
    auto c = async(launch::async, consumer, i);


auto c1 = async(launch::async, consumer, 1);
auto c2 = async(launch::async, consumer, 2);

【问题讨论】:

没有“时间”这回事。跨多个并发执行上下文的事件顺序只能根据可观察事件(即同步点)来定义。 请注意,即使两个线程“同时”开始运行,其中一个线程完全有可能在另一个线程开始执行其第二条指令之前运行完成。所以线程启动的确切时间基本上是无关紧要的。您应该考虑同步 线程之间的交互。 【参考方案1】:

其他答案所说的无法保证两个线程同时启动是正确的。不过,如果你想接近,有不同的方法可以做到这一点。

一种方法是使用一组 std::promises 来指示一切准备就绪。每个线程设置一个承诺以表明它已准备好,然后等待从第三个 std::promise 获得的(a 的副本)std::shared_future;主线程等待所有线程的所有承诺被设置,然后触发线程去。这可以确保每个线程都已启动,并且就在应该并发运行的代码块之前。

std::promise<void> go, ready1, ready2; // Promises for ready and go signals
std::shared_future<void> ready(go.get_future()); // Get future for the go signal
std::future<void> done1, done2; // Get futures to indicate that threads have finished
try

    done1 = std::async(std::launch::async, 
        [ready, &ready1]
    
        ready1.set_value(); // Set this thread's ready signal
        ready.wait(); // Wait for ready signal from main thread
        consumer(1);
    );
    done2 = std::async(std::launch::async,
        [ready, &ready2]
    
        ready2.set_value(); // Set this thread's ready signal
        ready.wait(); // Wait for ready signal from main thread
        consumer(2);
    );
    // Wait for threads to ready up
    ready1.get_future().wait();
    ready2.get_future().wait();
    // Signal threads to begin the real work
    go.set_value();
    // Wait for threads to finish
    done1.get();
    done2.get();

catch (...)

    go.set_value(); // Avoid chance of dangling thread
    throw;

注意:此答案的大部分内容是从 Anthony Williams 的“C++ Concurrency in Action”(第 311-312 页)复制而来,但我修改了代码以适合问题中的示例。

【讨论】:

【参考方案2】:

同时启动两个线程我认为没有其他方法,首先以经典方式启动 2 个线程,然后使用屏障阻塞它们以同步它们,但发布广播不能保证同时重新调度它们。 或者,您可以旋转检查全球时间计数器或其他东西,但即便如此......

【讨论】:

其实我发现上面两种创建线程的方式有不同的结果。第二种方式似乎更接近同时运行。【参考方案3】:

一次启动两个线程是不可能的。 CPU 一次只能做一件事。它通过停止一个线程、保存寄存器状态、恢复另一个线程的状态并执行该线程一段时间来进行线程化。把它想得更像这样(虽然不完全是它的工作原理)。

hey cpu, i want to do two things at once, eat apples and bananas

CPU 说

ok, well, heres what we will do. Eat a bit of an apple
now, eat some banana
repeat..

因此,您可以近距离启动它们,但不能同时启动。

【讨论】:

当计算机只有一个 CPU/核心时,情况就是如此。但在几乎任何现代 CPU 中,它都是错误的。几乎所有现代 CPU 都至少有两个内核,因此它们可以并且确实同时执行至少两个线程。 正确,请注意我说的(不完全正确)。一个好的进程调度器可以同时在多个内核上执行,但这取决于操作系统。一个好的经验法则是假设它们不是,并通过资源锁定和 CPU 等待来纠正它。 另外,对不起,如果我仍处于“石器时代”,但我使用的一切通常都是单核 ARM CPU

以上是关于c++线程异步同时运行的主要内容,如果未能解决你的问题,请参考以下文章

标准 C++ 中的异步线程

c++多线程同时运行两个函数该怎样编程啊?

什么是java的线程安全?同步,异步

在后台运行长时间运行的并行任务,同时允许小型异步任务更新前台

两个同时运行的线程控件(BackgroundWorker)串数据

如何在 c++ winform 中同时运行两个函数?