通过时钟类我们可以方便的查看程序运行时长,在程序优化时很有用处。结合条件变量,可以实现有条件逻辑的限时等待。同时支持限时等待的还有互斥,可以完成某些纯限时等待的简单逻辑。
将要执行函数放在两个时间点之间,求得时间差。
#include
#include
#include
#include
#include
#include
// using namespace std::chrono_literals;
void doSomething()
{
std::this_thread::sleep_for(
std::chrono::duration<int, std::ratio<1, 1>>(2));
std::cout << "doSomething" << std::endl;
}
auto main() -> int
{
auto start = std::chrono::high_resolution_clock::now();
doSomething();
auto stop = std::chrono::high_resolution_clock::now();
auto durations =
// std::chrono::duration
std::chrono::duration<double, std::ratio<1, 1>>
// std::chrono::duration_cast
(stop - start).count();
std::cout << "doSometing() took " << durations << " seconds" << std::endl;
return 0;
}
条件变量的限时等待函数 cv.wait_until(lk, timeout),阻塞线程,放开锁 lk,直至等到 timeout 时间点,或其他线程的通知,持有锁,进行下一步执行语句。
为了防止伪唤醒导致直接略过含有条件变量的 if 语句,需要将 if 语句嵌套在 while 循环中。
#include
#include
#include
#include
#include
#include
std::condition_variable cv;
bool done;
std::mutex m;
auto waitLoop() -> bool
{
auto const timeout =
std::chrono::steady_clock::now() + std::chrono::milliseconds(500);
std::unique_lock<std::mutex> lk(m);
while (!done)
{
if (cv.wait_until(lk, timeout) == std::cv_status::timeout)
{
std::cout << "break" << std::endl;
break;
}
}
return done;
}
auto main() -> int
{
waitLoop();
return 0;
}
std::timed_mutex 是可限时等待的互斥,利用其成员函数 try_lock_for(times) 可以在 times 时间之内试图加锁,也可用成员函数 try_lock_until(timePoint),在某时间点前尝试加锁。
以下示例可以更改 std::chrono::duration
auto timePoint = std::chrono::system_clock::now() + std::chrono::duration
的值查看获取锁的情况。
#include
#include
#include
#include
std::timed_mutex tm;
std::chrono::duration<double, std::ratio<1, 1>> Seconds(4);
void waitFor(int times, int id)
{
bool locks = tm.try_lock_for(Seconds);
std::this_thread::sleep_for(
std::chrono::duration<long, std::ratio<1, 1>>(times));
if (locks)
{
std::cout << "unlockTryLockFor" << id << std::endl;
locks = false;
tm.unlock();
}
}
void waitUntil()
{}
auto main() -> int
{
std::thread waitForTime1(waitFor, 2, 1);
std::thread waitForTime2(waitFor, 2, 2);
auto timePoint = std::chrono::system_clock::now() + std::chrono::duration<long, std::ratio<1, 1>>(5);
std::this_thread::sleep_for(
std::chrono::duration<long, std::ratio<1, 1>>(1));
bool locks = tm.try_lock_until(timePoint);
if (locks)
{
std::cout << "unlockTryLockUntil\n";
tm.unlock();
locks = false;
}
waitForTime1.join();
waitForTime2.join();
return 0;
}
限时等待在多线程并发编程的作用是梳理程序的时间线逻辑,以完成某些有关时效性的程序逻辑实现,可粗略的分为两类,等待一段时间(for),或等到某个时间点(until)。单独使用并不复杂,和其他程序逻辑搭配,会复杂不少,还需仔细斟酌。
参考文献:C++并发编程实战(第2版)[英] 安东尼•威廉姆斯(Anthony Williams)