当所有线程循环在主线程中结束迭代时发出通知

Notify when all thread loops ended their iteration in main thread

提问人:Jepessen 提问时间:10/11/2023 更新时间:10/11/2023 访问量:50

问:

我有以下代码:

#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>
#include <vector>
#include <syncstream>

int main() {
  std::condition_variable myCV;
  std::mutex myMutex;
  bool isRunning{ true };

  const size_t numberOfThreads{ 6 };

  std::vector<std::jthread> threads;

  for (size_t i = 0; i < numberOfThreads; i++) {
    threads.emplace_back(
      [&isRunning, &myMutex, &myCV, i]() {
        std::unique_lock loopLock(myMutex);
        while (isRunning) {
          myCV.wait(loopLock);
          std::this_thread::sleep_for(std::chrono::milliseconds(500));
        }
        std::osyncstream oss{ std::cout };
        oss << "Ended thread " << i << std::endl;
      }
    );
  }


  for (int i = 0; i < 100; i++) {
    myCV.notify_all();
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
    std::cout << "Test loop " << i << std::endl;
  }

  isRunning = false;
  myCV.notify_all();

  return 0;
}

该代码实例化了一些线程。每个线程都有一个内部无限循环,当条件变量通知它们时,迭代就开始了。myCV

这个想法是开始迭代,等待所有线程都工作,收集结果(此处未显示),然后开始下一次执行迭代。

我的问题是主线程不会等待所有线程循环迭代结束再继续,我不知道该怎么做。

我考虑过这样的解决方案:

#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>
#include <vector>
#include <syncstream>
#include <atomic>

int main() {
  std::condition_variable myCV;
  std::mutex myMutex;
  bool isRunning{ true };

  std::condition_variable loopEndCV;
  std::atomic<size_t> threadCounter{ 0 };
  std::mutex loopEndMutex;

  const size_t numberOfThreads{ 6 };

  std::vector<std::jthread> threads;

  std::cout << "Instantiating threads..." << std::endl;

  for (size_t i = 0; i < numberOfThreads; i++) {
    threads.emplace_back(
      [&, i]() {
        std::unique_lock loopLock(myMutex);
        while (isRunning) {
          myCV.wait(loopLock);
          std::this_thread::sleep_for(std::chrono::milliseconds(500));
          --threadCounter;
          if (threadCounter.load() == 0) {
            loopEndCV.notify_one();
          }
        }
        std::osyncstream oss{ std::cout };
        oss << "Ended thread " << i << std::endl;
      }
    );
  }


  for (int i = 0; i < 100; i++) {
    threadCounter = numberOfThreads;
    myCV.notify_all();
    std::unique_lock loopEndLock(loopEndMutex);

    loopEndCV.wait(loopEndLock, [&threadCounter]() { return threadCounter.load() == 0; });
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
    std::cout << "Test loop " << i << std::endl;
  }

  isRunning = false;
  myCV.notify_all();

  return 0;
}

基本上我添加了另一个,它应该在所有线程结束其循环迭代时发出通知,因此主线程会等待此操作,并且可以在所有迭代结束时继续进行。但是这完全阻止了程序(我在创建线程之前只打印字符串),所以我在某处遇到了一些死锁或其他类型的错误,我无法解决这个问题。std::condition_variable

我做错了什么?如何修复代码

C++ 多线程 循环死 条件变量

评论

1赞 G.M. 10/11/2023
听起来你正在寻找类似 std::barrier 的东西。
0赞 Botje 10/11/2023
仅仅因为您创建了 100 个线程并不意味着它们已经设法运行到该语句。此外,多个线程可以看到变为零并同时通知您的 loopEndCV。myCV.wait(loopLock)threadCounter
0赞 Red.Wave 10/11/2023
正如 @G.M. 所写的,去 .引用页面上的示例是进一步阐述的一个很好的起点。std::barrier
0赞 Jepessen 10/11/2023
谢谢。我会检查一下,这似乎对我的情况很好。std::barrier

答: 暂无答案