admin管理员组文章数量:1599536
定义于头文件 <condition_variable>
class condition_variable_any; (C++11 起)
condition_variable_any
类是 std::condition_variable 的泛化。相对于只在 std::unique_lock<std::mutex> 上工作的 std::condition_variable , condition_variable_any
能在任何满足 基本可锁定 (BasicLockable) 要求的锁上工作。
条件变量语义描述见 std::condition_variable 。
类 std::condition_variable_any
是 标准布局类型 (StandardLayoutType) 。它非 可复制构造 (CopyConstructible) 、 可移动构造 (MoveConstructible) 、 可复制赋值 (CopyAssignable) 或 可移动赋值 (MoveAssignable) 。
若锁是 std::unique_lock ,则 std::condition_variable 可能提供更好的性能。
构造函数
condition_variable_any(); (1) (C++11 起)
condition_variable_any(const condition_variable_any&) = delete;
(2) (C++11 起)
1) 构造 std::condition_variable_any
类型对象。
2) 复制构造函数被删除。
参数 (无)
异常
1) 可能抛出 std::system_error ,其 std::error_condition 若线程无权限创建条件变量,则等于 std::errc::operation_not_permitted ,若非内存资源限制阻止此初始化,则等于 std::errc::resource_unavailable_try_again ,或其他实现定义值。
析构函数
~condition_variable_any(); (1) (C++11 起)
销毁 std::condition_variable_any 类型对象。
若已通知所有线程,调用析构函数才是安全的。不要求它们已退出其对应的等待函数:一些线程仍然可等待重获得关联锁,或在重获得后等待被调度到运行。
一旦析构函数开始,程序员就必须确保没有线程试图等待在 *this 上,特别是在等待线程在循环中调用等待函数,或使用接收谓词的等待函数的重载时。
异常 (无)
通知一个等待的线程
void notify_one() noexcept; (C++11 起)
若任何线程在 *this 上等待,则调用 notify_one
会解阻塞等待线程之一。
参数 (无)
返回值 (无)
注意
notify_one()
/notify_all()
的效果与 wait()
/wait_for()
/wait_until()
的三个原子部分的每一者(解锁+等待、唤醒和锁定)以能看做原子变量修改顺序单独全序发生:顺序对此单独的 condition_variable 是特定的。譬如,这使得 notify_one()
不可能被延迟并解锁正好在进行 notify_one()
调用后开始等待的线程。
通知线程不必保有等待线程所保有的同一互斥上的锁;实际上这么做是劣化,因为被通知线程将立即再次阻塞,等待通知线程释放锁。然而一些实现(尤其是许多 pthread 的实现)辨识此情形,在通知调用中,直接从条件变量队列转移等待线程到互斥队列,而不唤醒它,以避免此“急促并等待”场景。
然而,在要求精确调度事件时,可能必须在处于锁下时通知,例如,在若满足条件则线程将退出程序,导致析构通知线程的 condition_variable 的情况下。互斥解锁之后,但在通知前的虚假唤醒可能导致通知在被销毁对象上调用。
调用示例
#include <iostream>
#include <condition_variable>
#include <thread>
#include <chrono>
std::condition_variable_any cv;
std::mutex cv_m;
int i = 0;
bool done = false;
void waits()
{
std::unique_lock<std::mutex> lk(cv_m);
std::cout << "Waiting... \n";
cv.wait(lk, [] {return i == 1;});
std::cout << "...finished waiting. i == 1\n";
done = true;
}
void signals()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Notifying falsely...\n";
cv.notify_one(); // 等待线程被通知 i == 0.
// cv.wait 唤醒,检查 i ,再回到等待
std::unique_lock<std::mutex> lk(cv_m);
i = 1;
while (!done)
{
std::cout << "Notifying true change...\n";
lk.unlock();
cv.notify_one(); // 等待线程被通知 i == 1 , cv.wait 返回
std::this_thread::sleep_for(std::chrono::seconds(1));
lk.lock();
}
}
int main()
{
std::thread t1(waits), t2(signals);
t1.join();
t2.join();
}
输出
通知所有等待的线程
void notify_all() noexcept; (C++11 起)
解阻塞全部当前等待于 *this 的线程。
参数 (无)
返回值 (无)
注意
notify_one()
/notify_all()
的效果与 wait()
/wait_for()
/wait_until()
的三个原子部分的每一者(解锁+等待、唤醒和锁定)以能看做原子变量修改顺序单独全序发生:顺序对此单独的 condition_variable 是特定的。譬如,这使得 notify_one()
不可能被延迟并解锁正好在进行 notify_one()
调用后开始等待的线程。
通知线程不必保有与等待线程所保有者相同互斥的锁;实际上这么做是劣化,因为被通知线程将立即再次阻塞,以等待通知线程释放锁。
调用示例
#include <iostream>
#include <condition_variable>
#include <thread>
#include <chrono>
std::condition_variable_any cv;
std::mutex cv_m; // 此互斥用于三个目的:
// 1) 同步到 i 的访问
// 2) 同步到 std::cerr 的访问
// 3) 为条件变量 cv
int i = 0;
void waits()
{
std::unique_lock<std::mutex> lk(cv_m);
std::cerr << "Waiting... \n";
cv.wait(lk, [] {return i == 1;});
std::cerr << "...finished waiting. i == 1\n";
}
void signals()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lk(cv_m);
std::cerr << "Notifying...\n";
}
cv.notify_all();
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lk(cv_m);
i = 1;
std::cerr << "Notifying again...\n";
}
cv.notify_all();
}
int main()
{
std::thread t1(waits), t2(waits), t3(waits), t4(signals);
t1.join();
t2.join();
t3.join();
t4.join();
}
输出
本文标签: 变量多线程条件conditionvariableany
版权声明:本文标题:c++11 多线程支持 条件变量(condition_variable_any)(一) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1728321586a1153893.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论