赖勇浩(http://laiyonghao.com)
javascript
线程是指进程中的一个单一顺序的控制流,是操做系统可以调度的最小单位,一个进程中能够有多条线程,分别执行不一样的任务。线程有内核线程和用户线程之分,但在本文中仅指内核线程。在软件开发中,使用线程有如下好处:
一、在多核或多路 CPU 的机器上多线程程序可以并发执行,提升运算速度;
二、把 I/O,人机交互等与密集运算部分分离,提高 I/O 吞吐量和增进用户体验。
线程的缺点也很明显:
一、建立一条线程须要较大的内存开销,致使不能建立海量的线程;
二、线程由操做系统调度(分配时间片),线程切换的 CPU 成本比较高,致使大量线程存在时大量 CPU 资源消耗在线程切换上;
三、同一进程的多条线程共享所有系统资源,在多线程间共享资源须要进入加锁,大量的锁开销不提,重要的是加大了编写程序的复杂性,这一点你看看有多少书名含有“多线程”三个字就明白写个多线程应用有多难了;
四、 I/O 方面,多线程帮助有限,以 TCP Socket Server 为例,若是每个 client connection 由一条专属的线程服务,那么这个 server 可能并发量很难超过 1000。为了进一步解决并发带来的问题,现代服务器都使用 event-driven i/o 了。
event-driven i/o 解决了并发量的问题,但引入了“代码被回调函数分割得零零碎碎”的问题。特别是当 event-driven i/o 跟 multi-threading 结合在一块儿的时候,麻烦就倍增了。解决这个问题的办法就使用绿色线程,绿色线程能够在同一个进程中成千上万地存在,从而能够在异步 I/O 上封装出同步的 APIs,典型的就是用基于 greenlet + libevent 开发的 python 库 gevent。绿色线程的缺陷在于操做系统不知道它的存在,须要用户进行调度,也就没法利用到多核或多路 CPU 了。为了解决这个问题,不少大牛都作出了巨大的努力,而且成果斐然,scala、google go 和 rust 都较好地解决了问题,下文以 rust 的并发模型为例讲一下。
rust 提出一个 Task 的概念,Task 有一个入口函数,也有本身的栈,并拥有进程堆内存的一部分,为方便理解,你能够把它看做一条绿色线程。rust 进程能够建立成千上万个 Tasks,它们由内建的调度器进行调度,由于 Tasks 之间并不共享数据,只经过 channels/ports 通讯,因此它们是可并行程度很高。rust 程序启动时会生成若干条(数量由 CPU 核数决定或运行时指定)线程,这些线程并行执行 Tasks,从而利用多个 CPU 核心。
如 上图,rust 应用程序不停地 spawn 出一个又一个 Tasks,它们由 tasks 调度器管理,在适当的时机,调度器会把某一个 Task 分配给原生线程执行,若是这个 Task 进入 I/O 等待或主动让出 CPU(sleep),那么这个 Task 会被交回给调度器,而相应的原生线程会执行另外一个新分派的 Task。尽管使用 rust 编程语言是不能建立线程的(直接调用 C 函数不算),但 rust 应用程序其实是多线程的(通常状况下),它可以充分地利用多核或多路 CPU。
综上,相似 rust 的 Task 的概念是比线程更好的并发模型,更安全,编写的代码也更加容易维护(关于维护性,我相信写过 gevent 程度或 go 程序的同窗会认同的)。线程固然不会消亡,但随着 scala/go/rust 的成熟,在能够预见的未来,线程会退到它呆着的角落:远离普通程序员,只有少数人须要了解它的细节。php
赖勇浩(http://laiyonghao.com)css
C++C++ 在 2011 年其实风头甚劲,C++2011 标准出台,gcc/msvc/clang 都很快速地支持了许多新特性,新兴的移动设备的性能较差,更是 C++ 的新舞台,在这个时候唱衰 C++,压力很大。我使用 C++ 年头很多,但除了在校的时候写过两个小游戏参加过两个比赛(分别是面向社会和面向大学生的)弄些证书好找工做之外,在工做中只用过大概不到一年半,作《斩 魂》(http://zh.163.com)的早期版本,写了服务器端的几条进程和客户端的 GameAI 部分。经验少,并且写得很差,因此基本上有人在 weibo 上问我 C++ 的问题,我都是转发给 @bnu_chenshuo 和 @miloyip 等真正的行家去回答的。因此实际上今天写这一篇,我底气非常不足,可是朋友们给前两篇很大面子,弄得我骑虎难下,只好硬着头皮写了。
前 文提到 C++ 的新标准,颇有必要提一下标准化对 C++ 的影响。首先咱们要确定标准定制对 C++ 的积极做用,但标准化过程当中的超长流程,一次次将 C++ 推向深渊。C++ 的第一个标准是 1998 年的 ISO/IEC 14882:1998,距离整个 90 年代最流行的 C++ 程序库 MFC(Microsoft Foundation Class Library)的第一个版本发行时间已经整整 6 年。1998 年,MFC 版本号为 6.0,与其一块儿发布的 Visual C++ 6.0 占有了巨大的市场。由于 MFC 发布得标准制定的时间早,因此 MFC 内部实现了许多后来标准库里也有的组件,好比各类数据结构容器。VC6 的市场占有率让 windows 平台下开发的许多 C++ 程序员甚至不知道有 STL,同时也无视 C++98 标准,从更兼容标准的 VC2002/2003 的市场占有率就能够看出来,直到今天,我知道国内很多公司仍是只用 VC6 的。
其实在 90 年代,计算机的运算能力有限,市场上很是须要一款性能较高、抽象较强的编程语言,C++ 得到了成功,但它标准化的时间过长,形成各类编译器有各自互不兼容的“方言”,成了它的第一个软肋。第一个瞄准这个软肋的就是 java,java 在 1995 年推出,虽然性能稍逊,但它有更高的抽象能力、也更安全,而且更容易跨平台,因此迅速得到了成功;第二个瞄准这个软肋的是 C#,微软不能推进 C++ 发展,又不肯 C++ 的市场被 java 鲸吞,因而在 2001 年推出了 C#,通过 10 年的发展和微软大量的金钱推广,C# 已经成功得到了它应有的江湖地位。
虽然 java/c# 都不是善类,但 C++ 在 21 世纪的第一个十年里仍然地位稳固,这是由于 Linux 和 MacOS X 大获成功,在这两个平台上 C++ 都是很是有竞争力的编程语言,C++ 天然水涨船高。但随着 web2.0 和 web app 概念的兴起,以及 CPU 的主频进一步提高,服务器端编程语言渐渐地对执行效率再也不敏感,而是更在乎程序员的开发效率,众多的脚本语言开始蚕食 C++ 的市场份额,从早期的 perl 到后期的 python/php/ruby,在 2005 年之后,C++/java/C# 等静态类型的编译型语言的市场份额都降低了,新兴的贵族是动态语言。面对动态语言在开发效率上的强劲挑战,C++ 社区除了在 2003 年对 C++98 作了小小的 patch,基本上睡着了,彻底没有应对之策,哦不,连应用的姿态都没有。
进入 21 世纪的第二个十年,市场又发生了变化,云计算越走越近,也许咱们中的大部分人今天还能够说只闻其声不见其形,但 The Data Center Is the Computer 这句话你们应该以为很务实:完成一个用户操做,在服务器端的进程间通讯次数史无前例地多。在这个十年,咱们须要这样的编程语言:
一、能充分利用现代 CPU 的计算能力,不只仅是多个核心,更是巨大的 L1/L2/L3 Cache、超线程等;
二、可以大量减少异步 I/O 的性能提高的同时带来的反作用:异步编程的复杂性以及对可维护性的伤害;
两 句话其实也能够压缩为一句:须要有更好的并发模型的语言。一开始你们都在已有的编程语言中寻找,而后找到了 erlang,实践证实 erlang 自有其局限,因此 google go/scala/rust 等新语言如同雨后春笋般拨地而出。C++2011 标准努力下降 C++ 的编程难度,并提供了线程库以支持现代 CPU,若是在 2005 年,这个标准绝对有竞争力,但在今天,它只能成为新的编程语言的垫脚石。正如 IE 最大的用处是用来下载其它浏览器,不久以后,也许会流行新的冷笑话:C++ 最大的用处就是用来实现其它编程语言。
市场一直在寻找一门中间的高级 语言,它上承 C 语言和汇编语言,下启脚本语言。C++ 最早抢占了高地,并在与 java/c# 的争斗中不落下风,但新的十年,它的对手又增长了 google go/scala/rust 等新锐,而且新的标准不可能在两三年内再次出台,两三年内新锐成长起来后,留给它的位置就很少了。
上 文讨论的基本上都是服务器编程,有必要再来看一下桌面和移动设备领域。首先看桌面软件,rust 是 mozilla 基金会开发系统程序语言的,它的定位是部分取代 C++ 开发 firefox 的浏览器,因此 rust 会进入桌面开发,google go 确定会顺道啃一口。移动设备方面,主要是 android、ios 和 windows phone,随着移动设备性能加强,编译型语言加脚本的模式就会占大头,编译型语言方面主要是 C++ 和 Objective-C 在竞争,C++ 会占上风(但需求量远远小于脚本,从 lua 在 2011 年的增加速度能够印证),可是谁知道 rust 之类的会不会进入移动设备呢,毕竟移动设备的 CPU 核心也愈来愈多了呀,C++ 仍是前景堪忧。
回首 C++ 的 30 年,展望它的将来,总结起来可能就是:标准化流程拖死人了。若是不是 15 年不能标准化,java/c# 的搅局可能不会出现;若是在 2005 年可以应对动态语言……若是云时代有更好的并发模型……
题 外话:java/c# 不会有 C++ 的问题,由于它们有本身的平台,有巨大的财富支撑。特别是平台的做用很是巨大,你能够想像一下若是 Adobe 有本身的浏览器或手机操做系统 ActionScript/MXML 会不会是今天的境地;也能够想像一下 google go 的飞速发展动力是什么。
html