博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++11并发机制
阅读量:4617 次
发布时间:2019-06-09

本文共 4661 字,大约阅读时间需要 15 分钟。

传统意义上OS提供的并发机制包含进程和线程两个级别。考虑到实际复杂性,c++11仅提供了线程并发机制。

c++11提供的线程并发机制主要位于四个头文件中:、、、、。
线程并发机制包括线程管理、原子操作、线程同步对象。

线程管理

c++11中将可并发执行的运算成为一个任务(task),在OS的线程模型中,一个任务就是一个线程,实际需要在创建时指定线程函数。c++基于此提供了更为优雅的线程处理模型,不需要关心类型转换和指针的处理,所有线程管理的模型是基于std::thread实现的。在c++中一个任务通常是指函数、函数对象或Lamda表达式。比如下面代码:

// thread util sample 1#include 
#include
using namespace std;void TaskFunc(){}class TaskObj{public: TaskObj(){} void operator()() {}};int main(int argc, char ** argv){ thread t_func{TaskFunc}; thread t_obj{TaskObj()}; t_func.join(); t_obj.join(); return 0;}

创建thread对象时,就是线程启动的时候;thread::join()函数用于等待线程函数执行完成。

线程启动时的参数传递

上面代码(sample 1)中线程函数没有参数,如果需要给线程函数传递参数可以参考下面代码(参数类型可按值传递、按指针传递或按类型传递)。

// thread util sample 2void TaskFunc(int i){}class TaskObj{public:    TaskObj(int i):m_value(i){}    void operator()()    {m_value=123;}private:    int m_value{0};};int main(int argc, char ** argv){       int cur_value{100};    thread t_func{TaskFunc, cur_value};    thread t_obj{TaskObj{cur_value}};        t_func.join();    t_obj.join();    return 0;}

原子操作

操作系统中轻量级的线程同步机制通常是原子操作,c++11提供了相应机制,所有文件位于中。主要包含std::atomic模板类和std::atomic_flag类。

具体的建议参考。下面是一个说明int自增的原子函数

// atomic::operator++ example#include 
// std::cout#include
// std::atomic#include
// std::thread#include
// std::vectorstd::atomic
ready{0};void AtomicIncreasement (int id) { ++ready;};int main(int argc, char** argv){ std::vector
threads; std::cout << "spawning 5 threads that do incereasement...\n"; for (int i=1; i<=5; ++i) threads.push_back(std::thread(AtomicIncreasement,i)); for (auto& th : threads) th.join(); std::cout << ready << std::endl; return 0;}

输出如下:

spawning 5 threads that do incereasement...

5

线程同步对象

c++11中提供了两种线程同步机制,mutex和condition_variable,分别对应Windows同步机制中的互斥量和事件。当然,c++中也对各个部分做了详细划分,以mutex为例,分为以下四种(位于头文件中):

  • mutex
  • recursive_mutex
  • timed_mutex
  • recursive_timed_mutex

同时也提供了辅助的机制,比如unique_lock、lock_guard用于实现自动锁定和释放mutex。

比如下面例子说明了mutex的调用逻辑:

// mutex example#include 
// std::cout#include
// std::thread#include
// std::mutexstd::mutex mtx; // mutex for critical sectionvoid print_block(int n, char c) { // critical section (exclusive access to std::cout signaled by locking mtx): mtx.lock(); for (int i=0; i
lck{mtx}; for (int i=0; i

针对windows下的WaitForMultipleObject函数,c++提供了defer_lcok和lock(可变参数模块),用于实现同时等待多个同步对象。

关于condition_variable的介绍,建议参考。

线程返回参数处理

传统的线程返回值,可以通过指针和引用处理,但如何实现类似windows下线程函数返回值的处理逻辑,c++也提供了这种机制,相关机制位于头文件中()。promise和packaged_task作为数据载体,future作为数据接收者。

下面是两个说明future和promise、packaged_task的使用。

// promise example#include 
// std::cout#include
// std::ref#include
// std::thread#include
// std::promise, std::futurevoid print_int (std::future
& fut) { int x = fut.get(); std::cout << "value: " << x << '\n';}int main (){ std::promise
prom; // create promise std::future
fut = prom.get_future(); // engagement with future std::thread th1 (print_int, std::ref(fut)); // send future to new thread prom.set_value (10); // fulfill promise // (synchronizes with getting the future) th1.join(); return 0;}
// packaged_task example#include 
// std::cout#include
// std::packaged_task, std::future#include
// std::chrono::seconds#include
// std::thread, std::this_thread::sleep_for// count down taking a second for each value:int countdown (int from, int to) { for (int i=from; i!=to; --i) { std::cout << i << '\n'; std::this_thread::sleep_for(std::chrono::seconds(1)); } std::cout << "Lift off!\n"; return from-to;}int main (){ std::packaged_task
tsk (countdown); // set up packaged_task std::future
ret = tsk.get_future(); // get future std::thread th (std::move(tsk),10,0); // spawn thread to count down from 10 to 0 // ... int value = ret.get(); // wait for the task to finish and get result std::cout << "The countdown lasted for " << value << " seconds.\n"; th.join(); return 0;}

附加说明

c++11也提供了其他机制比如thread_local线程局部变量的存储限定符、once_flag用于标识仅初始化一次的处理逻辑以及简化版的async()函数——支持局部语法的并行化。

本文涉及的代码可以直接从我的git下载: ,位于c++11目录下,名字前缀为thread_util_sample*.cpp。

转载于:https://www.cnblogs.com/tocy/p/cpp11_concurrency_utility.html

你可能感兴趣的文章
奥森图标和CSS特殊字体使用方法
查看>>
转载 https协议和http协议的区别
查看>>
Google Analytics添加到网站
查看>>
PageControl的小点点随ScrollView滑动而变动代码
查看>>
(十三)在ASP.NET CORE中使用Options
查看>>
关于博主
查看>>
【2014年2、3月份日常记录表(2014.2.24—3.31,36天)】
查看>>
Dreamweaver中的插件如何应用
查看>>
iTerm2中粘贴tab问题
查看>>
SPFA算法 - Bellman-ford算法的进一步优化
查看>>
Darknet卷基层浅层特征可视化教程
查看>>
Laplace算子和Laplacian矩阵
查看>>
CentOS7 搭建gitlab服务器
查看>>
CSS控制文字,超出部分显示省略号
查看>>
NSMutableAttributedString实现富文本 (实现不同颜色和字体、下划线)
查看>>
贝叶斯规则
查看>>
解决Centos/Redhat,命令不存在
查看>>
项目实战—小饭桌
查看>>
ubuntu服务器版相关命令
查看>>
gdb
查看>>