当前位置: 首页 > news >正文

网站制作需求文档保定企业自助建站

网站制作需求文档,保定企业自助建站,销售外包公司,建设网站软件下载一个空列表#xff0c;用两个函数#xff08;只可调用一次#xff09;轮流写入值#xff08;一个写奇数#xff0c;一个写偶数#xff09;#xff0c; 最终实现列表的值为1-100#xff0c;有序排列。 简单分析#xff1a;假设这两个函数分别为A和B#xff0c;A函数往… 一个空列表用两个函数只可调用一次轮流写入值一个写奇数一个写偶数 最终实现列表的值为1-100有序排列。 简单分析假设这两个函数分别为A和BA函数往列表中写奇数B函数往列表中写偶数。因为要求交替写若A先写则在B写一个偶数之前需要等待A先把上一个奇数写完B写完一个偶数之后需要通知AA写完一个奇数之后要通知B这就存在同步关系了自然就想到了使用条件变量。而两个函数只可调用一次那自然想到了使用线程让两个函数独立运行并使用条件变量来同步写操作。 来看看使用标准库提供的并发API如何实现上述功能代码示例如下 #include thread #include mutex #include vector #include condition_variable #include algorithm #include iostreamstd::mutex mtx; std::condition_variable cv; const int NUM 100; int current_tid 0; // 通过id来控制线程之间的同步顺序std::vectorint nums(NUM);// 通过参数 tid 来标识线程 void work_odd(int tid) {for (int i 1; i NUM; i) {std::unique_lockstd::mutex locker(mtx);cv.wait(locker, [](){ return current_tid tid; });if (i % 2 1) {nums[i - 1] i;}current_tid (current_tid 1) % 2;cv.notify_one(); // 唤醒阻塞在条件变量上的一个线程} }void work_even(int tid) {for (int i 1; i NUM; i) {std::unique_lockstd::mutex locker(mtx);cv.wait(locker, [](){ return current_tid tid; });if (i % 2 0) {nums[i - 1] i;}current_tid (current_tid 1) % 2;cv.notify_one();} }int main() {std::thread t1(work_odd, 0);std::thread t2(work_even, 1);t1.join();t2.join();std::for_each(nums.begin(), nums.end(), [](auto e){ std::cout e ; });std::cout std::endl; }以上面的代码为例先来快速上手一下在标准库中如何使用 thread 开启一个新的线程如何使用互斥量 mutex 来互斥的访问临界区以及如何使用条件变量 condition_variable 来实现线程之间的同步。 std::thread thread 的声明如下所示第一个参数为一个可调用对象第二参数表示一个可变参数。 template class Fn, class... Args explicit thread (Fn fn, Args... args);按照如上函数声明初始化一个 thread 对象后即开启了一个新的线程。在使用 thread 创建线程进行并发编程时需要注意以下几点 在开启一个新的线程后需要在恰当的位置调用 join 或 detach。调用 join 函数会使 调用线程 阻塞直至被调用线程运行结束。调用 detach 函数会使调用线程和被调用线程分离即thread 对象不能显示地传递返回值给 调用线程可以间接通过 promise 和 future 来实现。当使用 thread 进行并发编程时若线程执行过程中有异常产生会直接终止程序。因此在使用 thread 进行并发编程时需要在被调用线程中进行异常处理。 这里对上述注意事项中的第三点进行一个补充代码示例如下 void func() {std::cout start func std::endl;// 运行过程中有异常产生没有进行捕获throw std::runtime_error(runtime error);std::cout end func std::endl; }int main() {std::cout start main std::endl;// 尝试捕获异常但是无效try {std::thread t1(func);t1.join(); // 这样写是不对的《Effective Modern C》Item35 和 Item37 有解释} catch(const std::exception e) {std::cout e.what() std::endl;}std::cout end main std::endl; }/* 运行结果为 start main start func terminate called after throwing an instance of std::runtime_errorwhat(): runtime error Aborted */thread 的其他 API 使用方法文档中已有详细介绍这里不再赘述。对于上述列的三点注意事项展开说来又是一篇文章了。 std::mutex 使用 thread 开启一个新的线程非常简单一行代码就搞定。接下来介绍互斥量 (mutex) 的基本使用。 在C标准库中提供了好几种互斥量类型mutex、recursive_mutex、timed_mutex、recursive_timed_mutexC14增加了shared_timed_mutexC17增加了shared_mutex。本文只介绍 mutex 的基本使用。 mutex 是一种排他的互斥量在并发环境中进入临界区前先对互斥量进行加锁操作临界区访问结束后对互斥量进行解锁操作。mutex 的使用也很简单如下代码示例所示 std::mutex mtx; // 创建了一个互斥量// 进入临界区前先加锁若加锁失败当前线程之前已有其他线程加锁当前线程会被阻塞在该处 mtx.lock(); // 临界区 // ...... // 临界区 mtx.unlock();如上示例所示使用C标准库提供的 mutex 非常方便。但是上述形式的用法可能存在以下两个问题在并发编程中要尽量避免。 上述第8行的 mtx.unlock() 漏写导致互斥量没被解锁产生死锁现象。临界区内有异常发生且未被正确捕获则产生异常处之后的代码不会被执行即 mtx.unlock() 不会被执行产生死锁。 为避免上述两种的情况C标准库提供了非常方便的 mutex 管理类lock_guard 和 unique_lock基于C11C14增加了shared_lockC17增加了scoped_lock。本文只介绍 unique_lock若要全面介绍这四种 mutex 管理类及其使用场景又是另一篇文章了。 使用基于 unique_lock 解决使用原始 mutex 可能产生的两个问题代码示例如下 std::mutex mtx; // 创建了一个互斥量// 使用花括号限定 unique_lock 的作用域 {std::unique_lockstd::mutex locker(mtx);// 临界区// ......// 临界区 }unique_lock 类定义等价于如下代码 class unique_lock { public:explicit unique_lock(std::mutex m):mtx(m) {mtx.lock();} unique_lock(const unique_lock) delete;~unique_lock() {mtx.unlock();}private:std::mutex mtx; };因此使用 unique_lock 来管理 mutex 是一种资源获取即初始化Resource Acquisition Is InitializationRAII的思想。 std::condition_variable 在多线程环境中线程的执行过程在某个时间段内可能存在先后关系比如B线程运行到某个时刻点时需要等待A线程的某个特定事件发生后才能继续往下执行这种关系又称为同步。解决这种线程通信的问题的一种方案为 条件变量。 在C标准库中条件变量 std::condition_variable 的使用和 thread、mutex 一样简单C标准库提供了非常简洁的接口。接下来先来看看条件变量的基本用法长什么样然后结合上述的面试题来尝试总结如何使用条件变量解决线程间的同步关系。 条件变量的基本用法如下所示 std::condition_variable cv; //事件的条件变量 std::mutex mtx; //配合cv使用的mutex// 关键代码部分 {std::unique_lockstd::mutex locker(mtx);cv.wait(mtx, [](){ /* 等待事件是否发生的条件判断 */ });// 对事件进行反应执行相关操作。此时 mtx 已经上锁// ...// 可选的操作通知一个或所有等待该事件的线程// cv.notify_one();// cv.notify_all(); } // 退出该作用域unique_lock执行析构函数调用mtx.unlock()以上述的面试题为例看看 std::condition_variable 如何使用。简化的代码示例如下 std::condition_variable cv; //事件的条件变量 std::mutex m; //配合cv使用的mutex// 用来控制事件变化的变量 int current_tid 0; void func(int tid) {std::unique_lockstd::mutex locker(mtx);cv.wait(locker, [](){ return current_tid tid; });// ...// 相关操作// ...current_tid (current_tid 1) % 2; // 改变条件cv.notify_one(); // 唤醒阻塞在条件变量上的一个线程 }int main() {std::thread t1(func, 0);std::thread t2(func, 1);// 省略一些代码... }解释一下上述代码 若执行 func 函数的线程被阻塞则有可能有两种情况 进入函数体刚执行第9行语句时mutex 因被其他线程先调用 mtx.lock() 而被阻塞进入函数体后std::unique_lockstd::mutex locker(mtx); 语句将 mtx 锁住之后调用 cv.wait() 语句因为cv.wait() 语句的第二个参数返回 false 在上面示例中等价于 current_tid ! tidcv.wait() 该语句将当前线程阻塞在阻塞前会调用 mtx.unlock() 释放互斥锁然后当前被阻塞等待其他线程调用 cv.notify_one() 或 cv.notify_all() 将该线程唤醒。 若执行 func 函数的线程没被阻塞 线程顺利获取到 mutex 然后调用 cv.wait() 语句第二个参数返回 ture逻辑流程继续往下执行然后执行相关操作然后改变 current_tid 控制事件变化的变量值然后调用 cv.notify_one() 唤醒阻塞在该条件变量上的线程。 小结 使用条件变量控制线程之间的同步关系时关键在如何将事件变化的关系抽象出来用一个合适的变量数据结构来表示该事件的状态通过改变变量的值事件的状态来控制线程之间的同步关系。
http://www.zqtcl.cn/news/425846/

相关文章:

  • 企业解决方案网站做企业官网多少钱
  • 宁波网站建设哪家比较好怎麽做网站
  • 诸塈市建设局网站做移动网站开发
  • 南京建站公司网站网站视频源码地址
  • 德阳建设局网站做公众号首图的网站
  • 南阳网站优化渠道山西太原最新消息
  • 发布做网站需求qq群centos wordpress 建站教程
  • 东阳网站建设yw126南京网站改版
  • discuz视频网站模板徐州专业网站建设公司哪家好
  • 网站开发投资成本Wordpress显示成缩略图
  • 网站域名和网站网址吗中东跨境电商平台有哪些
  • 常宁市城乡和住房建设网站怎样加强文化建设
  • 视频网站如何做营销策划模板网站 seo
  • 中企动力做网站好吗网页建设软件
  • 爱站网seo浙江省嘉兴市建设局网站
  • 南宁做网站比较好的公司有哪些贵阳网站上门备案业务
  • 网络叶子 网站推广做一手房做那个网站好
  • 太仓网站建设平台成都家装设计公司排名
  • 现在建一个网站一年费用只要几百元如何建一个免费试用网站
  • 网站没有被收录销售型网站的建设流程及特点
  • 成都58手机微信网站建设名录近一周财经新闻热点
  • wordpress情侣网站源码微信开放平台官网登录
  • 网站改版提示无需改版有没有兼职做设计的网站
  • 网站sem怎么做网络建设设计方案
  • wap网站在线生成做饰品网站
  • 网站主机在哪里注册呢江西的赣州网站建设
  • 零基础网站建设视频教程建筑设计专业是干什么的
  • 淘客做网站的话虚拟主机多大重庆网上房地产网签合同查询
  • 官网建站网站seo关键字优化软件
  • 网站制作的内容什么好开发板用什么语言编程