不理解条件变量超时
condition variable timeout not understood
我正在尝试给线程超时。
我尝试使用 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();
}
我希望线程 T1 休眠 10 秒。由于我在主线程中为 wait_for
设置了 1 秒超时,因此我希望 after
在 t1 end
之前打印。
相反,t1 运行了 10 秒(打印 t1 end
),在打印 after
后仅 1 秒。
你能解释一下为什么它会这样吗?我应该怎么做才能让我的超时执行超时?
这与condition_variable
无关。在 10 秒睡眠之前,您在 waitSec
中有一个 unique_lock
,因此没有人能够在 10 秒内获得互斥锁,所以这一行:
std::unique_lock<std::mutex> lock(myMutex);
将等到 waitSec
结束并由 unique_lock
析构函数释放 mutex
。
您需要在任何其他线程锁定您的互斥量之前创建您的 condition_variable
。
在这种情况下您不需要使用条件变量,因为您在 t1 启动后只在主线程中休眠 1 秒。
您在线程 1 中锁定互斥锁的实际情况是:
std::unique_lock<std::mutex> lock(myMutex);
然后在主线程中你试图再次锁定这个互斥量(在 return 从 1 秒睡眠之后):
std::cout << "before" << std::endl;
std::unique_lock<std::mutex> lock(myMutex);
主线程只有在t1结束后才能获得这个锁(~9秒,共10秒)。然后程序会打印"before",成功获取锁后会等待任何事件1秒,因为:
conditionVariable->wait_for(lock,std::chrono::seconds(1));
并且没有人可以从等待中唤醒(通知)主线程,所以它只会平静地休眠 1 秒,然后打印 "after"
如此有效,您只需从线程函数中移除互斥锁定即可获得您想要的结果。由于您的主题不 interacting/share 相互资源
如果您需要等待一秒钟或直到线程完成,您可以这样做(请注意,这段代码并不理想,只是为了展示基本思想):
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;
}
发生这种情况是因为您的互斥量被锁定,而不是因为条件变量。
在 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));
因此,在 t1 线程 waitSec
函数 运行 中的互斥锁被释放之前,main() 中的代码无法继续执行,这发生在函数结束时。
睡觉时不要持有互斥体。
我正在尝试给线程超时。 我尝试使用 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();
}
我希望线程 T1 休眠 10 秒。由于我在主线程中为 wait_for
设置了 1 秒超时,因此我希望 after
在 t1 end
之前打印。
相反,t1 运行了 10 秒(打印 t1 end
),在打印 after
后仅 1 秒。
你能解释一下为什么它会这样吗?我应该怎么做才能让我的超时执行超时?
这与condition_variable
无关。在 10 秒睡眠之前,您在 waitSec
中有一个 unique_lock
,因此没有人能够在 10 秒内获得互斥锁,所以这一行:
std::unique_lock<std::mutex> lock(myMutex);
将等到 waitSec
结束并由 unique_lock
析构函数释放 mutex
。
您需要在任何其他线程锁定您的互斥量之前创建您的 condition_variable
。
在这种情况下您不需要使用条件变量,因为您在 t1 启动后只在主线程中休眠 1 秒。
您在线程 1 中锁定互斥锁的实际情况是:
std::unique_lock<std::mutex> lock(myMutex);
然后在主线程中你试图再次锁定这个互斥量(在 return 从 1 秒睡眠之后):
std::cout << "before" << std::endl;
std::unique_lock<std::mutex> lock(myMutex);
主线程只有在t1结束后才能获得这个锁(~9秒,共10秒)。然后程序会打印"before",成功获取锁后会等待任何事件1秒,因为:
conditionVariable->wait_for(lock,std::chrono::seconds(1));
并且没有人可以从等待中唤醒(通知)主线程,所以它只会平静地休眠 1 秒,然后打印 "after"
如此有效,您只需从线程函数中移除互斥锁定即可获得您想要的结果。由于您的主题不 interacting/share 相互资源
如果您需要等待一秒钟或直到线程完成,您可以这样做(请注意,这段代码并不理想,只是为了展示基本思想):
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;
}
发生这种情况是因为您的互斥量被锁定,而不是因为条件变量。
在 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));
因此,在 t1 线程 waitSec
函数 运行 中的互斥锁被释放之前,main() 中的代码无法继续执行,这发生在函数结束时。
睡觉时不要持有互斥体。