接上篇:C++新特性36_条件变量的使用,前面介绍了条件变量的引入和使用,本篇介绍C++中是如何封装的及如何使用?
C++新特性37_条件变量的C++封装
1. _Cnd_wait的使用
上篇的代码中主线程和子线程中均有_Mtx_lock(g_mtx);,在子线程中如果拿到锁,但是条件while (!g_isSet)成立,子线程陷入等待情况下,主线程是否可以拿到锁呢?
#include <iostream>
#include <string>
#include <mutex>
#include <thread>
//全局互斥体,用于同步
//用于发送消息
std::string g_str;
bool g_isSet = false;
//条件变量对象
_Cnd_t g_cnd;
//互斥体
_Mtx_t g_mtx;
//B 子线程
// 利用条件变量,可以控制线程执行的逻辑顺序,也可以用来传递消息
void worker_thread() {
//睡眠一段时间,使得可以转到主线程
//std::this_thread::sleep_for(std::chrono::seconds(1));
_Mtx_lock(g_mtx);
//子线程接收通知
while (!g_isSet) {
//都是原子性:不可以被打断
//1. 等待g_cnd被通知
//2. g_mtx 会被释放
//3. 当等到了g_cnd被触发时,g_mtx会被重新获取
_Cnd_wait(g_cnd, g_mtx); //陷入等待的过程,等到信号
}
printf("%s\r\n", g_str.c_str());
_Mtx_unlock(g_mtx);
}
//A 主线程
int main() {
//初始化 对应了构造函数,需要使用的是一个指针 _Cnd_init(_Cnd_t *)
_Cnd_init(&g_cnd);
//选择普通互斥体类型
_Mtx_init(&g_mtx, _Mtx_plain);
//起一条子线程
std::thread thd(worker_thread);
//std::this_thread::sleep_for(std::chrono::seconds(1)); //主线程休眠就可以保证子线程先执行等待主线程的信号
//主线程发送信号(通知)
_Cnd_signal(g_cnd);
_Mtx_lock(g_mtx);
g_isSet = true;
g_str = "Hello World!";
_Mtx_unlock(g_mtx);
//表示主线程已经准备完毕,通知子线程开始处理
//主线程发送信号(通知)
_Cnd_signal(g_cnd);//给条件变量发信号
thd.join();
//析构条件变量
_Cnd_destroy(g_cnd);
_Mtx_destroy(g_mtx);
return 0;
}
设置断点,运行结果如下:执行完子线程之后,主线程也是可以拿到锁的,如果拿不到,程序就会处于死锁的状态

因此条件变量的_Cnd_wait(g_cnd, g_mtx);等待语句隐藏了一层含义:等待条件变量对象g_cnd被通知;g_mtx 会被释放;当等到了g_cnd被触发时(发送信号),g_mtx会被重新获取。内部都是原子性操作
2.条件变量在C++中的封装类及使用
- condition_variable 是c++11对条件变量的封装,配合std::unique_lockstd::mutex进行wait操作。
- condition_variable_any,搭配任意带有lock、unlock语义的mutex使用,效率 condition_variable 低。
使用封装的代码如下,基本与上面的代码是一致的:
#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
std::string str;
bool g_isSet = false;
std::mutex m;
std::condition_variable cv;
void worker_thread() {
std::cout << "Worker thread start\n";
{
std::unique_lock<std::mutex> lk(m);
//利用匿名函数对上面while()的写法进行替换
cv.wait(lk, [&] {return g_isSet; });
std::cout << str.c_str() << std::endl;
}
std::cout << "Worker thread end\n";
}
int main() {
std::thread thd(worker_thread);
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lk(m);
g_isSet = true;
str = "hello";
}
cv.notify_one();
thd.join();
std::cout << "Main thread signals end\n";
}
运行结果:

3. 学习视频地址:条件变量的C++封装
本文详细解析了C++中条件变量的_Cnd_wait用法,并展示了如何通过C++11的condition_variable和unique_lock进行封装,以实现线程间的高效协作。通过实例演示了如何避免死锁,确保信号通知后的锁获取。
481

被折叠的 条评论
为什么被折叠?



