std::condition_variable 简单练习

std::condition_variable 和 std::condition_variable_any 都用于线程同步,前者只能与 std::unique_lock 配合,后者是前者泛化,可以和任何 lock 配合。线程同步是指线程间需要按照预定的先后次序顺序进行的行为。

综合运用std::mutex和std::condition_variable,可以让线程同步。

 

wait :阻塞当前线程,然后解锁,线程原地等待,丢弃 mutex 所有权,直到收到 notify 条件变为 true ,重新上锁,获取 mutex 所有权。(其中notify_one随机唤醒一个线程)

下面是 std::condition_variable::wait 用法:

std::mutex m;
std::condition_variable cv;
int i = 0;
void waits1() { std::unique_lock l(m); cout << "waits1 function for processing\n"; cv.wait(l, [] { return i == 1; }); // 先解锁(即丢弃 m 所有权),线程原地等待,直到条件改变为 true ,才重新加锁(即重新获取 m 所有权),并继续往下运行 cout << "waits1 function for processing\n"; i = 2; l.unlock(); // 手动解锁,减少 notify 后,其它线程对 m 所有权的获取时间 cv.notify_one(); // 通知条件变量改变 } void waits2() { std::unique_lock l(m); cout << "waits2 function for processing\n"; cv.wait(l, [] { return i == 2; }); // 先解锁,线程原地等待,直到条件改变为 true ,才重新加锁,并继续往下运行 cout << "waits2 function for processing\n"; } int main(int argc, char* argv[]) { system("chcp 65001"); std::thread t1(waits1); std::thread t2(waits2);

std::this_thread::sleep_for(10ms); // 延时10ms
{ std::lock_guard l(m); i
= 1; cv.notify_one(); // 通知条件变量改变,随机唤醒一个 cout << "temp function for processing\n";

QElapsedTimer timer; // 可以直接用sleep_for timer.start();
while (timer.elapsed() < 3000) {} std::cerr << "elapased time = "<<timer.elapsed()<< endl; } t1.join(); // 阻塞当前线程,直到函数运行完成 t2.join(); cout << "endl\n"; return 0; }

 

 

wait_for :阻塞当前线程,然后解锁,线程原地等待,丢弃 mutex 所有权,接下来有以下几个状态:

a、收到 notify,且条件变量改变为 true :

  • 重新上锁,获取 mutex 所有权,返回 true

b、未收到notify,且条件变量改变为 true :

  • 超过设定时间段后,重新上锁,获取 mutex 所有权,返回  true

c、未收到notify,且条件变量未改变为 true :

  • 超过设定时间段后,不重新上锁,不获取 mutex 所有权,返回 false

d、收到 notify,且条件变量未改变为 true :

  • 超过设定时间段后,不重新上锁,不获取 mutex 所有权,返回 false

下面是 std::condition_variable::wait_for 用法。

std::mutex cv_m;
std::condition_variable cv;
int i = 0;
void waits(int idx) { QElapsedTimer timer; timer.start(); std::unique_lock<std::mutex> lk(cv_m); if (cv.wait_for(lk, idx * 100ms, [] {return i == 1; })) std::cerr << "Thread " << idx << " finished waiting. i == " << i << '\n'; else std::cerr << "Thread " << idx << " timed out. i == " << i << '\n';
std::this_thread::sleep_for(100ms); // 延时100ms std::cerr
<< timer.elapsed() << endl; } int main(int argc, char* argv[]) { system("chcp 65001"); std::thread t1(waits, 2); std::thread t2(waits, 3); std::this_thread::sleep_for(10ms);
i
= 1; cv.notify_all(); // 若屏蔽,结果不一样 t1.join(); t2.join(); cout << "endl\n"; return 0; }

 

 未屏蔽 cv.notify_all()结果;

屏蔽 cv.notify_all()结果;

(两次延时差距100ms是因为  一个线程等待另一个线程是否丢弃 mutex 所有权)

 

 wait_until:和 wait_for 用法一致,唯一区别就是 “时间段” 变成 “绝对时间点” 。

//  wait_for
if
(cv.wait_until(lk, idx * 100ms, [] {return i == 1; })) // 时间段

// wait_until
auto now = std::chrono::system_clock::now();
if (cv.wait_until(lk, now + idx * 100ms, [] {return i == 1; })) // 绝对时间点

 

posted @ 2022-02-16 13:10  补码  阅读(71)  评论(0编辑  收藏  举报