在不同的线程中执行 lambda 函数

Posted

技术标签:

【中文标题】在不同的线程中执行 lambda 函数【英文标题】:execute a lambda function in different thread 【发布时间】:2021-09-26 23:29:07 【问题描述】:

由于固定要求,我需要在特定线程中执行一些代码,然后返回结果。同时应该阻塞启动该操作的主线程。

void background_thread()

  while(1)
  
    request.lock();
    g_lambda();
    response.unlock();
    request.unlock();
  


void mainthread()

  ...
  g_lambda = []()...;
  request.unlock();
  response.lock();
  request.lock();
  ...

这应该可行。但这给我们留下了一个大问题:后台线程需要从响应互斥锁开始,而主线程需要从请求互斥锁开始......

我们怎样才能做到这一点?我想不出什么好办法。这难道不是一种反模式吗?

【问题讨论】:

这个想法无论如何都是错误的。主线程执行request.unlock()后,后台线程可能会循环多次,多次执行lambda并解锁未锁定的响应互斥锁。 听起来你可能会更好地使用两个生产者-消费者队列:一个用于生成由辅助线程运行的 lambdas/任务的主线程,另一个用于辅助线程产生的结果和由主线程读取/处理。但是,正如所展示的那样,它确实看起来像一个 xy 问题。 请显示minimal reproducible example。 std::thread t(g_lambda); t.join(); 还不够吗(尽管毫无意义)? user253751 是对的。嗯.... @AlanBirtles 不,它必须是一个特定的线程,而不仅仅是任何后台线程。太糟糕了。我会考虑更多,并研究消费者队列的替代方案......谢谢。 【参考方案1】:

将任务传递给后台线程可以通过生产者-消费者队列来完成。不依赖于第三方库的简单 C++11 实现将具有 std::condition_variable,它由后台线程等待并由主线程通知,std::queue 任务和std::mutex 来保护这些。

可以通过std::promise/std::future 将结果返回到主线程。最简单的方法是将std::packaged_task作为队列对象,这样主线程创建packaged_task,将其放入队列,通知condition_variable并等待packaged_task的未来。

如果您要从一个线程一次创建一个任务,则实际上不需要std::queue - 只需一个std::unique_ptr<std::packaged_task>> 就足够了。队列增加了同时添加许多后台任务的灵活性。

【讨论】:

谢谢!一个问题:如果我知道我总是阻塞主线程,我可以删除 std::packaged_task 并直接使用 std::function 吗?返回值将使用相同的 condition_variable 发回信号。与 packaged_task + future 相比会有任何(性能)​​优势吗? 你可以。虽然我更喜欢不同的条件变量。可能会有性能优势。

以上是关于在不同的线程中执行 lambda 函数的主要内容,如果未能解决你的问题,请参考以下文章

MPI:如何启动三个将在不同线程中执行的函数

090_多线程

多线程与互斥锁

JAVA——进阶语法——使用lambda表达式(λ)进行函数式编程,对匿名内部内代码简化思路及案例在线程中的应用

如何在不同的线程中执行 QTcpSocket?

Java多线程-lambda表达式