admin管理员组文章数量:1599543
目录
写在前面
解析
wait函数
wait_for函数
wait_until函数
notify_one函数
notify_all函数
栗子
参考书籍
写在前面
condition_variable条件变量可以阻塞(wait、wait_for、wait_until)调用的线程直到使用(notify_one或notify_all)通知恢复为止
首先要知道condition_variable是一个类,这个类既有构造函数也有析构函数,使用时需要构造对应的condition_variable对象,调用对象相应的函数来实现上面的功能。
解析
wait函数
函数原型:
void wait (unique_lock<mutex>& lck);
template <class Predicate>
void wait (unique_lock<mutex>& lck, Predicate pred);
包含两种重载,第一种只包含unique_lock对象,另外一个Predicate 对象(等待条件),这里必须使用unique_lock,因为wait函数的工作原理:
当前线程调用wait()后将被阻塞并且函数会解锁互斥量,如果使用lock_guard则不能调用unlock函数,所以这里只能使用unique_lock对象,直到另外某个线程调用notify_one或者notify_all唤醒当前线程;一旦当前线程获得通知(notify),wait()函数也是自动调用lock(),同理不能使用lock_guard对象。
如果wait没有第二个参数,第一次调用默认条件不成立,直接解锁互斥量并阻塞到本行,直到某一个线程调用notify_one或notify_all为止,被唤醒后,wait重新尝试获取互斥量,如果得不到,线程会卡在这里,直到获取到互斥量,然后无条件地继续进行后面的操作
如果wait包含第二个参数,如果第二个参数不满足,那么wait将解锁互斥量并堵塞到本行,,直到某一个线程调用notify_one或notify_all为止,被唤醒后,wait重新尝试获取互斥量,如果得不到,线程会卡在这里,直到获取到互斥量,然后继续判断第二个参数,如果表达式为false,wait对互斥量解锁,然后休眠,如果为true,则进行后面的操作
wait_for函数
函数原型:
template <class Rep, class Period>
cv_status wait_for (unique_lock<mutex>& lck,
const chrono::duration<Rep,Period>& rel_time);
template <class Rep, class Period, class Predicate>
bool wait_for (unique_lock<mutex>& lck,
const chrono::duration<Rep,Period>& rel_time, Predicate pred);
和wait不同的是,wait_for可以执行一个时间段,在线程收到唤醒通知或者时间超时之前,该线程都会处于阻塞状态,如果收到唤醒通知或者时间超时,wait_for返回,剩下操作和wait类似
wait_until函数
函数原型:
template <class Clock, class Duration>
cv_status wait_until (unique_lock<mutex>& lck,
const chrono::time_point<Clock,Duration>& abs_time);
template <class Clock, class Duration, class Predicate>
bool wait_until (unique_lock<mutex>& lck,
const chrono::time_point<Clock,Duration>& abs_time,
Predicate pred);
与wait_for类似,只是wait_until可以指定一个时间点,在当前线程收到通知或者指定的时间点超时之前,该线程都会处于阻塞状态。如果超时或者收到唤醒通知,wait_until返回,剩下操作和wait类似
notify_one函数
函数原型:
void notify_one() noexcept;
解锁正在等待当前条件的线程中的一个,如果没有线程在等待,则函数不执行任何操作,如果正在等待的线程多余一个,则唤醒的线程是不确定的。
notify_all函数
函数原型:
void notify_all() noexcept;
解锁正在等待当前条件的所有线程,如果没有正在等待的线程,则函数不执行任何操作。
栗子
#include <iostream>
#include <string>
#include <thread>
#include <list>
#include <mutex>
class MesProcess
{
public:
void Inmsglist()
{
for (int i = 0; i < 10000; i++)
{
std::unique_lock<std::mutex> uniqlock(my_mutex);
std::cout << "Inmsglist线程正在执行,插入数字为:" << i << std::endl;
msglist.push_back(i);
my_cond.notify_one(); //尝试把wait和线程唤醒,执行完这里wait就会被唤醒
//如果添加线程Outmsg_thread2则需要将此处更换为notify_all更稳定
}
}
void Outmsglist()
{
int command = 0;
while (true)
{
std::unique_lock < std::mutex > uniqlock(my_mutex);
my_cond.wait(uniqlock, [this] { //这里的判断条件为lambda表达式,判断信息队列是否为空,为空返回false,否则返回true
if (!msglist.empty()) //调用wait函数
return true;
return false;
});
command = msglist.front();
msglist.pop_front();
std::cout << "Outmsglist线程"<<std::this_thread::get_id()<<"正在执行,取出数字为:" << command << std::endl;
uniqlock.unlock();
}
}
private:
std::list<int> msglist;
std::mutex my_mutex;
std::condition_variable my_cond; //生成一个条件变量对象
};
int main()
{
std::cout << "主线程的线程id为: " << std::this_thread::get_id() << std::endl;
MesProcess mpobj;
std::thread Outmsg_thread(&MesProcess::Outmsglist, &mpobj);
//std::thread Outmsg_thread2(&MesProcess::Outmsglist, &mpobj);
std::thread Inmsg_thread(&MesProcess::Inmsglist, &mpobj);
Inmsg_thread.join();
Outmsg_thread.join();
//Outmsg_thread2.join();
std::cout << "主线程运行结束" << std::endl;
return 0;
}
参考书籍
《C++11并发与多线程视频课程》 视频地址:http://edu.51cto/course/15287.html
C++11中std::condition_variable的使用
本文标签: 变量多线程条件conditionvariable
版权声明:本文标题:c++11多线程中的condition_variable(条件变量) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dianzi/1728323868a1154181.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论