这个C++多线程程序有什么问题?

dkqlctbz  于 2024-01-09  发布在  其他
关注(0)|答案(1)|浏览(156)

我使用std::thread编写了一个多线程C++程序,如下所示:

  1. #include <iostream>
  2. #include <thread>
  3. #include <mutex>
  4. #include <condition_variable>
  5. using namespace std;
  6. const int threadNum = 4;
  7. mutex mt[threadNum];
  8. condition_variable cv[threadNum];
  9. thread threadList[threadNum];
  10. bool threadWork[threadNum];
  11. void work(int id) {
  12. while (true) {
  13. unique_lock<mutex> lck(mt[id]);
  14. cv[id].wait(lck, [&]() { return threadWork[id]; }); // wait for incoming tasks
  15. // do something
  16. threadWork[id] = false;
  17. cv[id].notify_all();
  18. }
  19. }
  20. int main() {
  21. for (int i = 0; i < threadNum; i ++) {
  22. threadWork[i] = false;
  23. threadList[i] = thread(work, i);
  24. }
  25. while (true) {
  26. for (int i = 0; i < threadNum; i ++) {
  27. // allocate tasks for each threads
  28. threadWork[i] = true;
  29. cv[i].notify_all();
  30. }
  31. for (int i = 0; i < threadNum; i ++) {
  32. // wait until all tasks finish
  33. unique_lock<mutex> lck(mt[i]);
  34. cv[i].wait(lck, [&]() { return !threadWork[i]; });
  35. cout << "Finish thread " << i << endl;
  36. }
  37. // do something
  38. }
  39. for (int i = 0; i < threadNum; i ++)
  40. threadList[i].join();
  41. return 0;
  42. }

字符串
在程序的迭代过程中,主线程和子线程交替执行,主线程首先为多个子线程分配任务,所有线程完成任务后,主线程将汇总信息并进行其他计算。
但是,在执行过程中,程序会随机地在几次迭代后崩溃或陷入死锁。我不知道为什么会发生这种情况。这是什么问题?
我的环境:ubuntu 22.04,g++ 11.4

kyxcudwk

kyxcudwk1#

下面代码中的注解:

  1. //...
  2. mutex mt[threadNum]; // Mutexes are for synchronizing
  3. // between threads. Having 1 mutex
  4. // per thread is not proper the way
  5. // to guard access to data.
  6. // try having 1 mutex per block of
  7. // data that you want guarded instead.
  8. condition_variable cv[threadNum]; // same applies for the condition variables
  9. // you want to indicate that the DATA
  10. // is ready.
  11. // ...
  12. // The rest of the code will need a bit of reordering.

字符串
对于你的实验,你应该尝试一些更简单的方法,比如说,从一个受保护的数据块开始。下面是一个例子。
请注意,在下面的代码中,工作线程等待一个唯一的条件变量,告诉它们需要做一些事情。
我还添加了一个简单的机制,一旦工作完成,就可以优雅地从程序中退出。这和其他部分一样重要,注意原子<>的使用,它保证所有核心都会在值发生变化时看到。

  1. #include <condition_variable>
  2. #include <iostream>
  3. #include <mutex>
  4. #include <thread>
  5. #include <vector>
  6. #include <atomic>
  7. std::mutex my_data_mutex;
  8. std::condition_variable my_data_cv;
  9. std::vector<int> my_data;
  10. constexpr size_t threadNum = 4;
  11. std::atomic<bool> halt = false;
  12. void work(int id) {
  13. for(;;)
  14. {
  15. std::unique_lock<std::mutex> _(my_data_mutex);
  16. my_data_cv.wait(_); // wait for incoming tasks
  17. if (halt)
  18. return;
  19. // do something
  20. my_data.push_back(my_data.back() + id);
  21. }
  22. }
  23. int main() {
  24. std::vector<std::thread> tasks;
  25. for (int i = 0; i < threadNum; i++) {
  26. tasks.emplace_back(work, i);
  27. }
  28. while(!halt)
  29. {
  30. std::unique_lock<std::mutex> _(my_data_mutex);
  31. my_data.push_back(0); // do some silly job
  32. // note tht the worker threads
  33. // would seg fault when
  34. // the array is empty (try it!)
  35. // thank god, they're waiting, for now.
  36. if (my_data.size() > 1'000'000) // exit when job is done.
  37. halt = true; // tell all that the jobn is done
  38. my_data_cv.notify_all(); // tell all threads to do their silly part
  39. }
  40. for (auto& t : tasks)
  41. t.join();
  42. return 0;
  43. }

展开查看全部

相关问题