简体   繁体   English

等待线程超时:冻结

[英]waiting for thread with timeout: freeze

I don't understand anything now. 我现在什么都不懂。 Consider I have next piece of code (simplified version): 考虑我有下一段代码(简化版):

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

const auto k_sleep = std::chrono::seconds{3};
const auto k_wait = std::chrono::seconds{1};
const auto k_repeats = 20u;

void test()
{
    std::mutex m;
    std::condition_variable c;
    bool processed = false;

    std::thread worker{[&]() {
            std::this_thread::sleep_for(k_sleep);

            std::unique_lock<std::mutex> lock(m);
            processed = true;
            lock.unlock();
            c.notify_one();
        }};

    std::unique_lock<std::mutex> lock(m);
    if(c.wait_for(lock, k_wait, [&processed]() {
            return processed;
        }))
    {
        worker.join();
        std::cout << "done" << std::endl;
    }
    else
    {
        worker.detach();
        std::cout << "timeout" << std::endl;
    }
}

int main()
{
    for(auto i = 0u; i < k_repeats; ++i)
        test();
}

Few questions: 几个问题:

  • are there any deadlocks ? 有什么僵局吗?
  • am I using condition_variable (and all other stuff relative to thread ) correctly ? 我是否正确使用condition_variable (以及所有其他相对于thread东西)?
  • is there UB ? 有UB吗?
  • if everything OK, how many times timeout will be printed ? 如果一切正常,将打印多少次timeout

As you can see, I'm running thread and waiting for it (using condition_variable ) some time. 如您所见,我正在运行线程并等待一段时间(使用condition_variable )。 Wait time is less then thread's executing time. 等待时间少于线程的执行时间。

With both VC++ (Visual Studio 2015, v 19.00.23026) and g++ (v 4.8.2) I have timeout 2 times printed and then I'm stuck on worker.join() under debugger. 使用VC ++(Visual Studio 2015,v 19.00.23026)和g ++(v 4.8.2)时,我打印了2次timeout ,然后卡在调试器下的worker.join() If I will increase k_sleep to something big (relatively to k_wait with small loops count), for example, 30 seconds - everything will be fine. 例如,如果我将k_sleep增大到某个较大的值(相对于k_wait循环次数较小),例如30秒-一切都会好的。

So, why this happens ? 那么,为什么会这样呢? If I do something incorrectly please explain me the correct way. 如果我做错了什么,请向我解释正确的方法。 Thanks 谢谢

You have problems with memory management there: 您在那里的内存管理有问题:

  1. Capturing variables by reference in lambda that passed to a new thread. 通过传递给新线程的lambda中的引用捕获变量。
  2. All variables ( m , c and processed ) are allocated on the stack, and they will go out of scope when you detach a worker thread. 所有变量( mc和已processed )都分配在堆栈上,并且在分离工作线程时它们将超出范围。 So, when the thread wake up, it will access garbage. 因此,当线程唤醒时,它将访问垃圾。

So, you need to allocate you data on the heap and make sure you do not capture variables by reference. 因此,您需要在堆上分配数据,并确保不通过引用捕获变量。 I always prefer to pass data explicitly into std::thread . 我总是喜欢将数据显式传递到std::thread

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

const auto k_sleep = std::chrono::seconds{ 3 };
const auto k_wait = std::chrono::seconds{ 1 };
const auto k_repeats = 20u;


struct Data
{
   std::mutex m;
   std::condition_variable c;
   bool processed = false;
};

void test()
{
   auto data = std::make_shared<Data>();

   auto run = [](std::shared_ptr<Data> i_data) {
      std::this_thread::sleep_for(k_sleep);

      std::unique_lock<std::mutex> lock(i_data->m);
      i_data->processed = true;
      lock.unlock();
      i_data->c.notify_one();
   };

   std::thread worker{ run, data };

   std::unique_lock<std::mutex> lock(data->m);
   if (data->c.wait_for(lock, k_wait, [&data]() {
      return data->processed;
   }))
   {
      worker.join();
      std::cout << "done" << std::endl;
   }
   else
   {
      worker.detach();
      std::cout << "timeout" << std::endl;
   }
}

int main()
{
   for (auto i = 0u; i < k_repeats; ++i)
      test();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM