C ++ condition_variable wait_for()永远阻塞

时间:2020-02-03 10:10:36

标签: c++ linux wait condition-variable

在我的项目中,我有多个线程将数据馈送到工作池。工作线程使用条件变量等待新数据。这在几个小时甚至几天内都可以正常工作,但是有时工人会永远std::condition_variable::wait_for()挡住它。没有超时,也没有通知将其唤醒。我验证了工作线程仍然存在,它从未离开过wait_for()

工人的工作通常需要4到6毫秒。 pushWork()平均每5毫秒添加一次新作业。这些新作业不是定期创建的,而是10-20个作业的爆发。在下面的示例代码中,我使用一个带有睡眠的假人来代替复杂的实际工作。

为什么这种零星的封锁会永远发生?

我的代码的简化版本,简化为重要部分:

#include <chrono>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <vector>
#include <iostream>
#include <cstdlib>
#include <atomic>

class TestWorker
{
public:
  enum JobState
  {
    free = 0,
    processing
  };

  TestWorker() : workerThread(&TestWorker::doWork, this)
  {
  }

  ~TestWorker()
  {
    stopWorker = true;
    if (workerThread.joinable())
    {
      workerTrigger.notify_one();
      workerThread.join();
    }
  }

  void pushWork(const int data)
  {
    while (JobState::free != state)
    {
      std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
    std::lock_guard<std::mutex> lock(workerMutex);
    while (JobState::free != state)
    {
      std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
    // Set dummy data for job ...
    dummyData = data;
    state = JobState::processing;
    workerTrigger.notify_one();
  }

  void doWork()
  {
    std::unique_lock<std::mutex> triggerLock(workerMutex);
    while (!stopWorker)
    {
      if (JobState::processing == state)
      {
        // Do something for 4-6ms with dummy job data
        ++dummyData;
        std::this_thread::sleep_for(std::chrono::milliseconds(5));  // Dummy sleep instead of real job
        state = JobState::free;
      }
      else
      {
        if (!workerTrigger.wait_for(triggerLock,
                               std::chrono::milliseconds(500),
                               [this]
        { return (stopWorker || (JobState::processing == state)); }))
        {
          if (!stopWorker)
          {
            std::cout << "TIMEOUT" << std::endl;
          }
          else
          {
            std::cout << "EXIT" << std::endl;
          }
        }
      }
    }
  }

  std::mutex workerMutex;
  std::condition_variable workerTrigger;
  bool stopWorker = false;
  std::thread workerThread;
  std::atomic<JobState> state = { JobState::free };
  // Dummy data for job ...
  int dummyData = 0;
};

int main()
{
  std::cout << "START" << std::endl;

  std::vector<TestWorker> testWorkers(10);

  for (int i = 1; i <= 1000; ++i)
  {
    if (0 == i % 10)
    {
      std::cout << "Loop #" << i << std::endl;
    }
    for (auto it = testWorkers.begin(); it != testWorkers.end(); ++it)
    {
      it->pushWork(i);
    }
  }

  std::cout << "END" << std::endl;

  return 0;
}

编译与:g ++ workerTriggerTest.cc -o workerTriggerTest -pthread -std = c ++ 11

gcc版本4.8.5 20150623(红帽4.8.5-36)

CentOS Linux版本7.6.1810

0 个答案:

没有答案