设为首页 加入收藏

TOP

5分钟速成C++14多线程编程(一)
2019-03-25 04:07:39 】 浏览:157
Tags:5分钟 速成 线程 编程

原文链接:Learn C++ Multi-Threading in 5 Minutes

  C++14的新的多线程架构非常简单易学,如果你对C或者C++很熟悉,那么本文非常适合你。作者用C++14作为基准参考,但是所介绍的东西在C++17中也依然适用。本文只介绍基本的架构,在读完本文后你应该也可以自己编写自己的多线程程序。

创建线程

创建线程有以下几种方式:

1.使用函数指针

2.使用仿函数

3.使用lambda表达式

这些方式都比较类似,只有部分差别,我将在下面具体讲述每一种方式和他们的区别。

使用函数指针

  来看看下面这个函数,其参数包括一个vector的引用 v ,一个输出结果的引用acm,还有两个v的索引。这个函数会将v的beginIndex和endIndex之间的元素累加起来。

1 void accumulator_function2(const std::vector<int> &v, unsigned long long &acm, 
2                             unsigned int beginIndex, unsigned int endIndex)
3 {
4     acm = 0;
5     for (unsigned int i = beginIndex; i < endIndex; ++i)
6     {
7         acm += v[i];
8     }
9 }

  现在如果我们想将vector分为两个部分,并在单独的线程t1和t2中分别计算各部分的总和的话,我们可以这么写:

 1 //Pointer to function
 2     {
 3         unsigned long long acm1 = 0;
 4         unsigned long long acm2 = 0;
 5         std::thread t1(accumulator_function2, std::ref(v), 
 6                         std::ref(acm1), 0, v.size() / 2);
 7         std::thread t2(accumulator_function2, std::ref(v), 
 8                         std::ref(acm2), v.size() / 2, v.size());
 9         t1.join();
10         t2.join();
11 
12         std::cout << "acm1: " << acm1 << endl;
13         std::cout << "acm2: " << acm2 << endl;
14         std::cout << "acm1 + acm2: " << acm1 + acm2 << endl;
15     }

上面这段你需要知道:

  1.std::thread这个调用创建了一个新的线程。其第一个参数是函数指针 accumulator_function2 ,因此每个线程都会去执行这个函数。

  2.剩下的我们传给std::thread的构造函数的参数,都是我们需要去传给accumulator_function2的参数。

  3.重点:传递给accumulator_function2的参数默认情况下都是值传递的,除非你用std::ref把他包起来。所以我们这里使用了std::ref来包住v、acm1、acm2。

  4.使用std::thread创建的线程是没有返回值的,所以如果你想从线程中返回些什么,请使用引用将你想返回的值作为一个传入参数。这里的例子就是acm1和acm2。

  5.每个线程一旦创建就立即执行了。

  6.我们使用join()函数来等待线程执行完毕。

使用伪函数

  你也可以使用伪函数来做同样的事情,下面是例子:

 1 class CAccumulatorFunctor3
 2 {
 3   public:
 4     void operator()(const std::vector<int> &v, 
 5                     unsigned int beginIndex, unsigned int endIndex)
 6     {
 7         _acm = 0;
 8         for (unsigned int i = beginIndex; i < endIndex; ++i)
 9         {
10             _acm += v[i];
11         }
12     }
13     unsigned long long _acm;
14 };

  那么创建线程的方式变成下面这样:

 1 //Creating Thread using Functor
 2     {
 3 
 4         CAccumulatorFunctor3 accumulator1 = CAccumulatorFunctor3();
 5         CAccumulatorFunctor3 accumulator2 = CAccumulatorFunctor3();
 6         std::thread t1(std::ref(accumulator1), 
 7             std::ref(v), 0, v.size() / 2);
 8         std::thread t2(std::ref(accumulator2), 
 9             std::ref(v), v.size() / 2, v.size());
10         t1.join();
11         t2.join();
12 
13         std::cout << "acm1: " << accumulator1._acm << endl;
14         std::cout << "acm2: " << accumulator2._acm << endl;
15         std::cout << "accumulator1._acm + accumulator2._acm : " << 
16             accumulator1._acm + accumulator2._acm << endl;
17     }

上面这段你需要知道:

  伪函数的使用方式大部分地方都和函数指针很像,除了:

  1.第一个参数变成了伪函数对象。

  2.我们不再需要使用引用来获取返回值了,我们可以将返回值作为伪函数对象的一个成员变量来储存。这里的例子就是_acm。

使用lambda表达式

  作为第三种选择,我们可以在每个线程的构造函数中使用lambda表达式来定义我们想做的事,如下:

 1 {
 2         unsigned long long acm1 = 0;
 3         unsigned long long acm2 = 0;
 4         std::thread t1([&acm1, &v] {
 5             for (unsigned int i = 0; i < v.size() / 2; ++i)
 6             {
 7                 acm1 += v[i];
 8             }
 9         });
10         std::thread t2([&acm2, &v] {
11             for (unsigned int i = v.size() / 2; i < v.size(); ++i)
12             {
13                 acm2 += v[i];
14             }
15         });
16         t1.join();
17         t2.join();
18 
19         std::cout << "acm1: " << acm1 << endl;
20         std::cout << "acm2: &
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C++编程丨让你的C++代码变的更加.. 下一篇[HNOI2015] 开店

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目