文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C++11 condition_variable条件变量怎么使用

2023-07-02 17:12

关注

今天小编给大家分享一下C++11 condition_variable条件变量怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

1 什么是条件变量

condition_variable是一个类,常和mutex搭配使用。

condition_variable类是一个同步原语,可用于阻塞一个线程或同时阻止多个线程,直到另一个线程修改共享变量并通知condition_variable。

防止多线程场景下,共享变量混乱。

理解条件变量要先理解三个概念:

2 condition_variable类定义

C++11 condition_variable条件变量怎么使用

2.1 wait函数

void wait( std::unique_lockstd::mutex& lock );//Predicate是lambda表达式。template< class Predicate >void wait( std::unique_lockstd::mutex& lock, Predicate pred );//以上二者都被notify_one())或notify_broadcast()唤醒,但是//第二种方式是唤醒后也要满足Predicate的条件。//如果不满足条件,继续解锁互斥量,然后让线程处于阻塞或等待状态。//第二种等价于while (!pred()){wait(lock);}

3 condition_variable用法

condition_variable必定至少有两方,一方是资源修改线程,一方是资源等待线程。就跟打篮球一样,同时篮球只会在一个人手中,投篮后就释放了篮球所有权,其他方就会抢夺篮球所有权。

3.1 资源修改线程步骤

3.2 资源等待线程步骤

(1)条件变量满足,线程继续执行

(2)条件变量不满足,wait会释放unlock锁,并挂起线程。

4 代码示例

4.1 无需notify场景

当wait第一次执行是,条件已经满足,则程序不会阻塞(即无需notify),会直接向下执行。(仅为说明3.2 中第2点(1)的情况)

#include <iostream>#include <string>#include <thread>#include <mutex>#include <condition_variable>using namespace std;std::mutex m;std::condition_variable cv;std::string data;bool ready = false;bool processed = false; void worker_thread(){    std::cout << "3、worker_thread子线程开始执行"  << endl;    // Wait until main() sends data    std::unique_lock<std::mutex> lk(m);    std::cout << "4、worker_thread子线程获取到锁,条件满足无需notify,不阻塞向下执行"  << endl;    cv.wait(lk, []{return ready;});     // after the wait, we own the lock.    data += " after processing";    // Send data back to main()    processed = true;    std::cout << "5、Worker thread signals data processing completed\n";     // Manual unlocking is done before notifying, to avoid waking up    // the waiting thread only to block again (see notify_one for details)    lk.unlock();    std::cout << "6、worker_thread子线程交出执行权限,主线程执行"  << endl;    std::this_thread::sleep_for(std::chrono::milliseconds(2000));        cv.notify_one();    std::cout << "9、worker_thread调用 notify_one"  << endl;}int main(){    std::thread worker(worker_thread);    std::cout << "1、主线程开始执行"  << std::endl;    data = "Example data";    // send data to the worker thread    {        //std::this_thread::sleep_for(std::chrono::milliseconds(1000));        std::lock_guard<std::mutex> lk(m);        ready = true;    }    std::cout << "2、锁已经释放了,主线程休眠,子线程执行"  << std::endl;    std::this_thread::sleep_for(std::chrono::milliseconds(1000));    //cv.notify_one();    {        std::cout << "7、主线程data:" << data << endl;        std::unique_lock<std::mutex> lk(m);        std::cout << "8、主线程条件满足无需notify" << endl;        cv.wait(lk, []{return processed;});    }        worker.join();     std::cout << "10、主线程结束" << endl;}

执行结果:

C++11 condition_variable条件变量怎么使用

4.2 正常应用场景1

#include <iostream>#include <string>#include <thread>#include <mutex>#include <condition_variable>using namespace std;std::mutex m;std::condition_variable cv;std::string data;bool ready = false;bool processed = false; void worker_thread(){    std::cout << "3、worker_thread子线程开始执行"  << endl;    // Wait until main() sends data    std::unique_lock<std::mutex> lk(m);    std::cout << "4、worker_thread子线程获取到锁,条件不满足,释放lk锁,子线程阻塞"  << endl;    cv.wait(lk, []{return ready;});    std::cout << "8、worker_thread子线程获取到锁,子线程继续执行"  << endl;    // after the wait, we own the lock.    data += " after processing";    // Send data back to main()    processed = true;    std::cout << "9、Worker thread signals data processing completed\n";     // Manual unlocking is done before notifying, to avoid waking up    // the waiting thread only to block again (see notify_one for details)    lk.unlock();    std::this_thread::sleep_for(std::chrono::milliseconds(5000));    std::cout << "10、worker_thread调用 notify_one通知主线程执行"  << endl;    cv.notify_one();}int main(){    std::thread worker(worker_thread);    std::cout << "1、主线程开始执行"  << std::endl;    data = "Example data";    // send data to the worker thread    {        std::cout << "2、主线程休眠,子线程进入执行"  << std::endl;        std::this_thread::sleep_for(std::chrono::milliseconds(1000));        std::cout << "5、主线程结束休眠,主线程获取lk锁,进入执行"  << std::endl;        std::lock_guard<std::mutex> lk(m);        ready = true;            }    std::cout << "6、主线程释放lk,调用notify通知子线程"  << std::endl;    cv.notify_one();    {        std::cout << "7、由于主线程的执行时钟周期未结束,继续执行主线程获取lk, wait检查条件不满足,释放锁" << endl;        std::unique_lock<std::mutex> lk(m);        cv.wait(lk, []{return processed;});    }       worker.join();     std::cout << "11、主线程结束" << endl;}

执行结果:

这里notify执行后不一定立即执行子线程,如果cpu执行时钟周期未结束,则主线程会继续执行. 所以7,8,9,10顺序可能变化参见4.3

同时4.1也会因为cpu时钟周期,执行顺序有所变动

C++11 condition_variable条件变量怎么使用

4.3 正常应用场景2

#include <iostream>#include <string>#include <thread>#include <mutex>#include <condition_variable>using namespace std;std::mutex m;std::condition_variable cv;std::string data;bool ready = false;bool processed = false; void worker_thread(){    std::cout << "3、worker_thread子线程开始执行"  << endl;    // Wait until main() sends data    std::unique_lock<std::mutex> lk(m);    std::cout << "4、worker_thread子线程获取到锁,条件不满足,释放lk锁,子线程阻塞"  << endl;    cv.wait(lk, []{return ready;});    std::cout << "8、worker_thread子线程获取到锁,子线程继续执行"  << endl;    // after the wait, we own the lock.    data += " after processing";    // Send data back to main()    processed = true;    std::cout << "9、Worker thread signals data processing completed\n";     // Manual unlocking is done before notifying, to avoid waking up    // the waiting thread only to block again (see notify_one for details)    lk.unlock();    std::cout << "10、worker_thread调用 notify_one通知主线程执行"  << endl;    cv.notify_one();}int main(){    std::thread worker(worker_thread);    std::cout << "1、主线程开始执行"  << std::endl;    data = "Example data";    // send data to the worker thread    {        std::cout << "2、主线程休眠,子线程进入执行"  << std::endl;        std::this_thread::sleep_for(std::chrono::milliseconds(1000));        std::cout << "5、主线程结束休眠,主线程获取lk锁,进入执行"  << std::endl;        std::lock_guard<std::mutex> lk(m);        ready = true;            }    std::cout << "6、主线程释放lk,调用notify通知子线程"  << std::endl;    cv.notify_one();    {        for(int i = 0; i< 10000000; i++)        {            int j = i;        }        std::cout << "7、由于主线程的执行时钟周期未结束,继续执行主线程获取lk, wait检查条件不满足,释放锁" << endl;        std::unique_lock<std::mutex> lk(m);        cv.wait(lk, []{return processed;});    }        worker.join();    std::cout << "11、主线程结束" << endl;}

执行结果:

C++11 condition_variable条件变量怎么使用

以上就是“C++11 condition_variable条件变量怎么使用”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯