C++ 条件变量不会使用 time_point::max() 在 wait_until() 上阻塞线程?

问题描述 投票:0回答:1

下面的代码不会阻塞线程,它会进入无限循环并继续打印

等待...

等待...

我的想法是,线程应该在 max() 时间上阻塞,当它设置为 now() 时,它应该解除线程的阻塞并执行业务。有什么想法吗?我用的是VS2013

#include "stdafx.h"
#include <iostream>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <chrono>

std::condition_variable condVar;
std::mutex mut;
bool pred = false;
auto dueAt = std::chrono::steady_clock::time_point::max();

void threadFunc()
{
    for (;;)
    {
        std::unique_lock<std::mutex> lock(mut);
        dueAt = std::chrono::steady_clock::time_point::max();

        if (condVar.wait_until(lock, dueAt, [](){ return pred; }))
        {
            std::cout << "Ready..." << std::endl;
            pred = false;
            dueAt = std::chrono::steady_clock::time_point::max();
        }
        else
        {
            std::cout << "Waiting..." << std::endl;
        }
    }
}

void notifierThread()
{
    for (int i = 0; i < 5; i++)
    {
        std::this_thread::sleep_for(std::chrono::seconds(5));
        {
            std::lock_guard<std::mutex> lock(mut);
            dueAt = std::chrono::steady_clock::now();
            pred = true;
            std::cout << " Signalling..." << std::endl;
        }
        condVar.notify_one();
    }
}


int _tmain(int argc, _TCHAR* argv[])
{
    std::thread t1(threadFunc);
    std::thread t2(notifierThread);
    t1.join();
    t2.join();
    return 0;
}
c++ c++11 visual-studio-2013 wait condition-variable
1个回答
0
投票

您的编译器很旧并且有错误?

#include <iostream>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <chrono>

std::condition_variable condVar;
std::mutex mut;
bool pred = false;
bool shutdown = false;
int result = 0;

void threadFunc()
{
  for (;;)
  {
    std::unique_lock<std::mutex> lock(mut);

    condVar.wait(lock, [](){ return pred || shutdown; });

    if (shutdown) {
      std::cout << "Shutdown!" << std::endl;
      break;
    }
    std::cout << "Ready... #" << result << std::endl;
    pred = false;
    ++result;
  }
}

void notifierThread()
{
  for (int i = 0; i < 5; i++)
  {
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    {
      std::lock_guard<std::mutex> lock(mut);
      pred = true;
      std::cout << " Signalling... #" << i << std::endl;
    }
    condVar.notify_one();
  }
}


int main()
{
    std::thread t1(threadFunc);
    std::thread t2(notifierThread);
    t2.join();
    while (true) {
      std::this_thread::sleep_for(std::chrono::milliseconds(100));
      std::lock_guard<std::mutex> l(mut);
      if (result == 5)
      {
        std::cout << " Signalling Shutdown!" << std::endl;
        shutdown = true;
        break;
      }
    }
    condVar.notify_one();
    t1.join();
    return 0;
}

这是程序的完整终止版本,不使用

dueAt

dueAt
时操纵
.wait_until
应该不会有任何作用(除非由于竞争条件而导致 UB,你用锁避免了这种情况)。 您的 C++
std
实现似乎有一个错误。

您到底想做什么还不清楚,所以我将您的代码转换为(可能)停止的代码。

实际上,您不能假设以这种方式发送 5 个信号会导致 5 个接收,因为

sleep(100 ms)
不能保证为读取器线程提供读取。 更合适的程序会发送一个计数器:

#include <iostream>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <chrono>

std::condition_variable condVar;
std::mutex mut;
int counter = 0;
bool shutdown = false;
int consumed = 0;

void threadFunc()
{
  for (;;)
  {
    std::unique_lock<std::mutex> lock(mut);

    auto old_count = counter;
    condVar.wait(lock, [old_count](){ return (counter != old_count) || shutdown; });

    if (shutdown) {
      std::cout << "Shutdown!" << std::endl;
      break;
    }
    std::cout << "Ready... #" << old_count << ".." << counter << std::endl;
    consumed = counter;
  }
}

void notifierThread()
{
  std::this_thread::sleep_for(std::chrono::milliseconds(250));
  for (int i = 0; i < 5; i++)
  {
    if (i%2)
      std::this_thread::sleep_for(std::chrono::milliseconds(100));
    {
      std::lock_guard<std::mutex> lock(mut);
      ++counter;
      std::cout << " Signalling... #" << i << " with count " << counter << std::endl;
    }
    condVar.notify_one();
  }
}


int main()
{
    std::thread t1(threadFunc);
    std::thread t2(notifierThread);
    t2.join();
    while (true) {
      std::this_thread::sleep_for(std::chrono::milliseconds(100));
      std::lock_guard<std::mutex> l(mut);
      if (consumed == 5)
      {
        std::cout << " Signalling Shutdown!" << std::endl;
        shutdown = true;
        break;
      }
    }
    condVar.notify_one();
    t1.join();
    return 0;
}

这里我让生产者变得飘忽不定,有时快有时慢。 然而,消费者可以一次处理超过 1 个信号。

© www.soinside.com 2019 - 2024. All rights reserved.