文档章节

C++11 并发编程教程 - Part 1 : thread 初探(bill译)

 天下杰论
发布于 2013/12/29 18:50
字数 1088
阅读 642
收藏 0

C++11 引入了一个新的线程库,包含了用于启动、管理线程的诸多工具,与此同时,该库还提供了包括互斥量、锁、原子量等在内的同步机制。在这个系列的教程中,我将尝试向大家展示这个新库提供的大部分特性。

   为了能够编译本文的示例代码,你需要有一个支持 C++11 的编译器,笔者使用的是 GCC4.6.1(你需要添加 "-std=c++11" 或 "-std=c++0x" 编译选项以启动 GCC  C++11 的支持)[译注:bill 的编译环境为 GCC4.6.3 + codeblocks 10.05 + Ubuntu 12.04,所使用的编译选项为 "-std=gnu++0x"]。


启动线程

   启动一个新的线程非常简单,当你创建一个 std::thread 的实例时,它便会自行启动。创建线程实例时,必须提供该线程将要执行的函数,方法之一是传递一个函数指针,让我们以经典的 "Hello world" 来阐释这一方法:


1
2
3
4
5
6
7
8
9
10
#include <thread>
#include <iostream>
void  hello(){
    std::cout <<  "Hello from thread "  << std::endl;
}
int  main(){
    std::thread t1(hello);
    t1.join();
    return  0;
}


   所有的线程工具均置于头文件 <thread> 中。这个例子中值得注意的是对函数 join() 的调用。该调用将导致当前线程等待被 join 的线程结束(在本例中即线程 main 必须等待线程 t1 结束后方可继续执行)。如果你忽略掉对 join() 的调用,其结果是未定义的 —— 程序可能打印出 "Hello from thread" 以及一个换行,或者只打印出 "Hello from thread" 却没有换行,甚至什么都不做,那是因为线程main 可能在线程 t1 结束之前就返回了。


区分线程

   每个线程都有唯一的 ID 以便我们加以区分。使用 std::thread 类的 get_id() 便可获取标识对应线程的唯一 ID。我们可以使用 std::this_thread 来获取当前线程的引用。下面的例子将创建一些线程并使它们打印自己的 ID


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <thread>
#include <iostream>
#include <vector>
void  hello(){
    std::cout <<  "Hello from thread "  << std::this_thread::get_id() << std::endl;
}
int  main(){
    std::vector<std::thread> threads;
    for(int  i = 0; i < 5; ++i){
        threads.push_back(std::thread(hello));
    }
    for(auto&  thread  : threads){
        thread.join();
    }
    return  0;
}

   依次启动线程并将他们存入 vector 是管理多个线程的常用伎俩,这样你便可以轻松地改变线程的数量。回到正题,就算是上面这样短小简单的例子,也不能断定其输出结果。理论情况是:


1
2
3
4
5
Hello from thread 140276650997504
Hello from thread 140276667782912
Hello from thread 140276659390208
Hello from thread 140276642604800
Hello from thread 140276676175616


   但实际上(至少在我这里)上述情况并不常见,你很可能得到的是如下结果:


1
2
3
4
Hello from thread Hello from thread Hello from thread 139810974787328Hello from thread 139810983180032Hello from thread
139810966394624
139810991572736
139810958001920

   或者更多其他的结果。这是因为线程之间存在 interleaving 。你没办法控制线程的执行顺序,某个线程可能随时被抢占,又因为输出到 ostream 分几个步骤(首先输出一个 string,然后是 ID,最后输出换行),因此一个线程可能执行了第一个步骤后就被其他线程抢占了,直到其他所有线程打印完之后才能进行后面的步骤。


使用 Lambda 表达式启动线程

   当线程所要执行的代码非常短小时,你没有必要专门为之创建一个函数,取而代之的是使用 Lambda表达式。我们可以很轻易地将上述例子改写为使用 Lambda 表达式的形式:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <thread>
#include <iostream>
#include <vector>
int  main(){
    std::vector<std::thread> threads;
    for(int  i = 0; i < 5; ++i){
        threads.push_back(std::thread([](){
            std::cout <<  "Hello from thread "  << std::this_thread::get_id() << std::endl;
        }));
    }
    for(auto&  thread  : threads){
        thread.join();
    }
    return  0;
}

   如上,我们使用了 Lambda 表达式替换掉原来的函数指针。毋庸置疑,这段代码和之前使用函数指针的代码实现了完全相同的功能。


下篇

   在本系列的下一篇文章中,我们将看到如何使用锁机制保护我们的并发代码。

本文转载自:http://billhoo.blog.51cto.com/2337751/1294190

共有 人打赏支持
粉丝 54
博文 443
码字总数 23611
作品 0
沈阳
项目经理
私信 提问
【C++11 并发编程教程 - Part 1 : thread 初探(bill译)】

C++11 并发编程教程 - Part 1 : thread 初探 注:文中凡遇通用的术语及行话,均不予以翻译。译文有不当之处还望悉心指正。 原文:C++11 Concurrency - Part 1 : Start Threads C++11 引入了一...

技术小胖子
2017/11/09
0
0
C++11 并发 —— 第一部分:启动线程

C++11 引入一个全新的线程库,包含启动和管理线程的工具,提供了同步(互斥、锁和原子变量)的方法,我将试图为你介绍这个全新的线程库。 如果你要编译本文中的代码,你至少需要一个支持 C+...

红薯
2012/03/22
7.9K
12
C++11 并发 —— 第一部分:启动线程

C++11 引入一个全新的线程库,包含启动和管理线程的工具,提供了同步(互斥、锁和原子变量)的方法,我将试图为你介绍这个全新的线程库。 如果你要编译本文中的代码,你至少需要一个支持 C+...

王振威
2012/11/27
1K
0
C++并发编程库--Theron

Theron是一个轻量级的C++并发编程库,其实现了Actor模式,利用Theron可以轻松地实现并发编程。Theron的API清晰简洁,而且支持*NIX、windows、ARM、MAC等多种平台,且支持pthreads, Windows t...

benney
2013/12/02
2.9K
0
收藏的博客 -- 高性能Linux服务器

http://zhuanlan.51cto.com/columnlist/shenj/ --- 58沈剑 http://blog.csdn.net/analogouslove --- 范蠡&张小方 http://blog.csdn.net/column/details/15700.html --- teamtalk https://gi......

libaineu2004
2017/08/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

《傲慢与偏见》的读书笔记与读后感作文2400字

《傲慢与偏见》的读书笔记与读后感作文2400字: 作者:孙苑馨;笔者按:读书这个习惯是我爸妈养出来的。小时候父母赚的钱除了吃饭穿衣剩下的就是买书了,他们除了买各种新鲜出版的文艺派图书...

原创小博客
7分钟前
0
0
oozie job 的挂了监控报警或重启

oozie Coordinator 的job 和actioni状态很多,但好像不支持设置某状态如failed后30分钟后自动重新拉启,因他的条件只有几种:触发条件可以是一个时间频率、一个dataset实例是否可用,或者可能...

hblt-j
26分钟前
1
0
python精简笔记-[6]-条件判断[if]语句

语法: if 判断条件: 执行语句……elif 判断条件:    执行语句……elif 判断条件:    执行语句……else: 执行语句…… 实例1: n = input("请输入您的性别: "...

平头哥-Enjoystudy
29分钟前
0
0
RxJava 是如何实现线程切换的(上)

前言 通过前一篇的从观察者模式出发,聊聊RxJava,我们大致理解了RxJava的实现原理,在RxJava中可以非常方便的实现不同线程间的切换。subscribeOn 用于指定上游线程,observeOn 用于指定下游线...

亭子happy
56分钟前
2
0
想晋级高级工程师只知道表面是不够的!Git内部原理介绍

本文由云+社区发表 作者:腾讯工蜂用户:王二卫 从不一样的视角了解git,以便更好的使用git 一、git & git 版本库认识 git 是一个内容寻址的文件系统,其核心部分是一个简单的键值对数据库(...

腾讯云加社区
59分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部