文章目录
- 1.C++11条件变量
- 2. 相关api方法
- 2.1 wait方法
- 2.2 wait_for 方法
- 2.3 wait_until 方法
- 2.4 notify_one 和 notify_all 方法
- 3虚假唤醒等问题
1.C++11条件变量
std::condition_variable 是 C++11 标准库中提供的一个类,用于在多线程环境中实现线程间的同步和通信。通常与 std::mutex(互斥锁)一起使用,以实现线程的等待和唤醒机制。
2. 相关api方法
2.1 wait方法
wait 方法用于阻塞当前线程,直到另一个线程调用同一 condition_variable 对象的 notify_one() 或 notify_all() 方法来唤醒等待的线程。wait 方法有两种形式:
第一种
void wait(std::unique_lockstd::mutex& lock);
当前线程的执行会被阻塞,直到收到 notify 为止。在等待过程中,会自动释放与 lock 关联的互斥锁,以允许其他线程访问共享资源。当线程被唤醒后,它会自动重新获取互斥锁,然后继续执行。
第二种
template< class Predicate>
void wait(std::unique_lockstd::mutex&
lock, Predicate pred);
这是一个带谓词的版本,线程仅在 pred 返回 false 时被阻塞。如果 pred 返回 true,则线程不会被阻塞,并继续执行。这有助于避免虚假唤醒,因为线程在唤醒后会重新检查条件是否满足。
2.2 wait_for 方法
wait_for 方法用于阻塞当前线程,直到另一个线程调用 notify 方法唤醒它,或者直到指定的超时时间到达。它也有两种形式:
第一种
template<class Rep, class Period> cv_status
wait_for(std::unique_lockstd::mutex& lock, const
std::chrono::duration<Rep, Period>& rel_time);
在指定的相对时间 rel_time 内,线程被阻塞。如果在这段时间内线程被唤醒,则返回 cv_status::no_timeout;如果超时,则返回 cv_status::timeout。
第二种
template<class Rep, class Period, class Predicate> bool
wait_for(std::unique_lockstd::mutex& lock, const
std::chrono::duration<Rep, Period>& rel_time, Predicate pred);
与第一种形式类似,但增加了谓词 pred。线程仅在 pred 返回 false 时被阻塞,并且如果在超时前 pred 变为 true 或线程被唤醒,则返回 true;如果超时且 pred 仍为 false,则返回 false。
2.3 wait_until 方法
wait_until 方法用于阻塞当前线程,直到另一个线程调用 notify 方法唤醒它,或者直到指定的绝对时间点到达。它同样有两种形式:
template<class Clock, class Duration> cv_status
wait_until(std::unique_lockstd::mutex& lock, const
std::chrono::time_point<Clock, Duration>& abs_time);
在指定的绝对时间点 abs_time 之前,线程被阻塞。如果在这段时间内线程被唤醒,则返回 cv_status::no_timeout;如果到达指定时间点仍未被唤醒,则返回 cv_status::timeout。
template<class Clock, class Duration, class Predicate> bool
wait_until(std::unique_lockstd::mutex& lock, const
std::chrono::time_point<Clock, Duration>& abs_time, Predicate pred);
与第一种形式类似,但增加了谓词 pred。线程在 pred 返回 false 且未到达 abs_time 时被阻塞。如果在这段时间内 pred 变为 true 或线程被唤醒,则返回 true;如果到达 abs_time 且 pred 仍为 false,则返回 false。
2.4 notify_one 和 notify_all 方法
void notify_one() noexcept;
唤醒等待在 condition_variable 对象上的单个线程。如果有多个线程在等待,则唤醒哪一个是不确定的。
void notify_all() noexcept;
唤醒等待在 condition_variable 对象上的所有线程。
3虚假唤醒等问题
1.std::condition_variable 必须与 std::unique_lock 一起使用,以确保在等待条件时以互斥方式访问共享资源。
2.虚假唤醒(spurious wakeup)是多线程环境中的一种正常行为,因此在使用 wait、wait_for 和 wait_until 方法时,应该总是重新检查条件是否满足,即使用while循环检查