将 std::thread 与 std::mutex 一起使用

Posted

技术标签:

【中文标题】将 std::thread 与 std::mutex 一起使用【英文标题】:Using std::thread with std::mutex 【发布时间】:2014-10-20 04:51:20 【问题描述】:

我正在尝试使用独立线程进行互斥锁。要求是,我有许多线程将独立运行并访问/更新公共资源。为了确保通过单个任务更新资源,我使用了互斥锁。然而,这是行不通的。

我已经粘贴了代码,这是我在下面尝试做的一个表示:

#include <iostream>
#include <map>
#include <string>
#include <chrono>
#include <thread>
#include <mutex>
#include <unistd.h>


std::mutex mt;
static int iMem = 0;
int maxITr = 1000;


void renum()

    // Ensure that only 1 task will update the variable
    mt.lock();
    int tmpMem = iMem;
    usleep(100); // Make the system sleep/induce delay
    iMem = tmpMem + 1;    
    mt.unlock();
    printf("iMem = %d\n", iMem);


int main() 

    for (int i = 0; i < maxITr; i++) 
        std::thread mth(renum);
        mth.detach(); // Run each task in an independent thread
    
    return 0;

但这会因以下错误而终止:

terminate called after throwing an instance of 'std::system_error'
  what():  Resource temporarily unavailable

我想知道上面 .detach() 的用法是否正确?如果我使用 .join() 它可以工作,但我希望每个线程独立运行,而不是等待线程完成。 我也想知道实现上述逻辑的最佳方法是什么。

【问题讨论】:

当您从main() 返回时,进程将退出,因此线程中尚未完成的任何工作都不会完成。等待他们使用join()main() 在返回之前做的一件完美的事情。 个线程似乎有点过头了。试着用一些可管理的东西来解决这个问题; (如 3)。而且你没有在等待你的线程,所以一旦你完成抛出线程main()就会终止,完成你的进程;可能不是你想要的。为此,我建议线程分离是错误的。相反,您应该将它们强加到std::vector&lt;&gt;,然后在main() 终止之前加入它们全部 @MichaelBurr 感谢您的评论。那么如果我使用.join(),每个线程是独立运行还是等待前一个线程完成?我的要求是每个线程都应该独立运行。感谢您的帮助。 警告,你正在用你的 printf 在锁外阅读iMem [OT]:您可以使用std::lock_guard(或std::unique_lock)代替锁定/解锁自己。或者也许使用std::atomic 【参考方案1】:

试试这个:

int main()

  std::vector<std::thread> mths;
  mths.reserve(maxITr);
  for (int i = 0; i < maxITr; i++) 
    mths.emplace_back(renum);
  
  for (auto& mth : mths) 
    mth.join();
  

这样,您可以保留对线程的控制(通过不调用detach()),并且您可以在最后加入它们,这样您就知道它们已经完成了任务。

【讨论】:

谢谢。我需要 1 澄清。 thread.join() 会让每个任务独立运行还是所有剩余任务都必须等待主任务完成(.join())? 线程将被允许独立运行和完成,除了等待所有线程的主线程(具体来说,它将等待mths[0]完成,然后等待@987654324 @ 完成,等等,但当然线程可以按任何顺序完成。 您是说 mths[1] 将仅在 mths[0] 完成后运行,而与访问共享对象无关?或者两者都将并行运行,但在访问共享资源 (iMem) 时,mths[1] 将等待 mths[0] 从 iMem 对象中释放锁? 线程并发运行;唯一的序列化部分是您按顺序join()他们。这一切都很好。无法保证哪个线程将“首先”执行。

以上是关于将 std::thread 与 std::mutex 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

mingw std::thread 与 Windows API

C++11 多线程std:: async与std::thread的区别

具有与 std::thread 不同的线程库的 C++ thread_local

使用std :: thread将多个线程的数组组合在一起使用std :: thread

使用std :: thread将多个线程的数组组合在一起使用std :: thread

C++11 的 std::thread 是不是与 POSIX 信号量兼容?