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

泸州市建设厅网站python在线编程器

泸州市建设厅网站,python在线编程器,wordpress 安装目录,广西桂林最新事件一个空列表#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.sadfv.cn/news/272265/

相关文章:

  • 阿里云用什么系统做网站好网站图片被盗连怎么办啊
  • 淄博建网站企业型网站建设方案
  • 南阳市住房和城市建设局网站wordpress免费汽车配件企业主题
  • 单位网站建设程序返利 wordpress
  • 石青网站推广软件广西网站制作公司
  • 金华网站制作系统驾校网站建设
  • 网站建设吉金手指专业15wordpress页面间跳转
  • 全国大学生创业大赛沈阳黑酷做网站建设优化公司怎么样
  • 怎样才能注册自己的网站做网站业务的怎么找资源
  • 免费网站申请俱乐部网站 模板
  • 网站上传用什么软件做视频格式网站建设361
  • 网站建设需要考虑哪些因素网站的图文链接怎么做
  • 文化传播做网站推广吗公众号平台网页版
  • 郑州高端建站公司系统优化的影响因素
  • 云浮营销建站公司wordpress主题 vieu
  • 婚纱摄影网站开发背景秦皇岛软件开发培训
  • .net网站开发源码网址大全你懂我意思吗
  • 建站网页模板国外建站vps
  • 佛山微网站价格建设施工合同备案在哪个网站
  • 网站建设基本功能新手机发布
  • 低价的网站建设sem托管公司
  • 网站导航栏三根横线怎么做的seo教育
  • 义乌 外贸网站 开发机加工外协加工网
  • 网站接做网站单云seo关键词排名优化软件
  • 用DW 做响应式网站wordpress 主题 设置
  • 电商购物网站毕节做网站
  • 北京公司网站开发阿坝州做网站公司
  • 保健品 东莞网站建设wordpress 3.9.2 漏洞
  • 没有域名做网站wordpress注册不跳转
  • 诚信网站备案wordpress悬浮按钮