条件变量超时不明白

时间:2016-05-19 07:42:15

标签: c++ multithreading c++11 condition-variable

我正在玩试图给线程超时。 我尝试使用std::condition_variable::wait_for,但这种行为与我预期的不同。

这是我的简单代码:

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

std::mutex myMutex;

void waitSec(int seconds)
{
    std::cout <<"t1 start" <<std::endl;
    std::unique_lock<std::mutex> lock(myMutex);
    std::this_thread::sleep_for(std::chrono::seconds(seconds));
    std::cout <<"t1 end" <<std::endl;
}

int main(void)
{
    // launch thread that sleeps 10s
    std::thread t1(waitSec,10);
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // wait for lock during max 1 second
    std::condition_variable* conditionVariable = new std::condition_variable();
    std::cout << "before" << std::endl;
    std::unique_lock<std::mutex> lock(myMutex);
    conditionVariable->wait_for(lock,std::chrono::seconds(1));
    std::cout << "after" << std::endl;

    t1.join();
}

我希望Thread T1能够睡10秒钟。由于我向主线程中的wait_for提供1s超时,我希望在after之前打印t1 end

相反,t1运行10秒(打印t1 end)并且打印after后仅1秒。

你能解释一下为什么它表现得像这样,我该怎么办才能让我的超时表现为超时?

3 个答案:

答案 0 :(得分:2)

这与sourceSets无关。在你的10秒睡眠之前,condition_variable中有一个unique_lock,所以没有人能够获得10秒的互斥量,所以这一行:

waitSec

将等到std::unique_lock<std::mutex> lock(myMutex); 结束并由waitSec析构函数释放mutex

您需要在任何其他线程锁定互斥锁之前创建unique_lock

答案 1 :(得分:1)

在这种情况下你不需要使用条件变量,因为你在t1 start之后只需在主线程中休眠1秒。

在线程1中锁定互斥锁实际上发生了什么:

std::unique_lock<std::mutex> lock(myMutex);

然后在主线程中你试图再次锁定这个互斥锁(从1秒睡眠返回后):

std::cout << "before" << std::endl;
std::unique_lock<std::mutex> lock(myMutex);

只有在t1完成后(~9秒,总共10秒),主线程才能获得此锁定。然后程序将打印“之前”并成功获取锁定并等待任何事件1秒,因为:

conditionVariable->wait_for(lock,std::chrono::seconds(1));

并且没有人可以从等待中唤醒(通知)主线程,因此它将平静地睡眠1秒然后打印“之后”

如此有效地你可以从线程函数中获取你想要的只是删除互斥锁定的内容。由于您的线程没有与其他人交互/共享资源

如果您需要等待一秒钟或直到线程完成,您可以执行以下操作(请注意此代码不理想,只是为了显示基本想法):

std::condition_variable cv;

void worker_thread()
{
    // do something
    // ...
    cv.notify_one();
}

int main() {
   std::thread t1(worker_thread);

   std::cout << "before" << std::endl;
   std::unique_lock<std::mutex> lock(myMutex);
   cv.wait_for(lock,std::chrono::seconds(1));
   std::cout << "after" << std::endl;
}

答案 2 :(得分:1)

这是因为您的互斥锁被锁定,而不是因为条件变量。

在main()中,您尝试在此处获取1行中的互斥锁:

std::unique_lock<std::mutex> lock(myMutex);
conditionVariable->wait_for(lock,std::chrono::seconds(1));

但是你的线程t1在这里保存互斥锁:

std::unique_lock<std::mutex> lock(myMutex);
std::this_thread::sleep_for(std::chrono::seconds(seconds));

因此,main()中的代码无法继续,直到t1线程运行的waitSec函数中的互斥锁被释放,这在函数结束时发生。

在睡觉时不要拿着互斥锁。