多线程,当今在IT圈子内部最普遍的概念。有多少人理解它的实质,它的精髓?(我不甚懂,这篇文章只是在使劲往前冲的时候让我停下了,吃点有营养的东西,然后继续冲)甚至在多线程还没有完全吃透的情况下,现在又冒出了什么并行计算,网格,云等等......
做技术应该迷恋技术,但不应该迷信技术!要吃透它,上升到理论的高度!
在计算机时代早期,只有任务,后来有了批处理,但是本质上还是一个任务,后来为了更加密集的应用资源产生了多道程序设计,这就开始了多进程时代,世界开始热闹了。多进程(多道程序设计)本质上是在一台硬件机器上虚拟N台硬件机器,有了N台机器,那么很自然的就可以跑N个进程了,这样,计算机领域的最伟大的 思想诞生了-----虚拟分层思想。该思想本质上是在某层(n层)通过外加一个下层(n-1层)的管理模块,向上层(n+1层)提供一个完整的抽象,这个 抽象可以让上层(n+1)的模块认为自己完全运行在下层(n-1)。这很拗口,我用实例说明一下:我把机器硬件设想为n-1层,多进程操作系统作为n层, 而应用软件为n+1层,我们看看是不是这个道理,每个进程(应用软件)都认为自己享有了整个机器,其他进程被操作系统这个管理者给隔离了,进城间通信被假象成两台不同机器的通信,所以古老又伟大的unix把套接字作为进程间通信的手段的一种。分层虚拟思想有两个很重要的层面,一个是隔离,一个是共享,很矛盾,但却是共存的,也许这就是我们的世界吧。隔离和共享再抽象一点就是个性和共性,隔离的是个性,共享的是共性。在我举的例子里面,共享的是硬 件,隔离的是进程私有的东西。按照科学界的做法,总是出一个量化的东西,那么我说:共享的是n层往下包括n层的东西(共享n-1层往下的层就没多大意义了,概念上是共享,但是注意,分层思想的另一个核心就是屏蔽,n层会为n+1层屏蔽掉n层下面层次的异构性),隔离的是n+1层的东西。这么说就很简单 了,但是这只是个开始,随着讨论的深入,我会把层次进一步的分割或合并,最终产生我们正
在用的windows或linux,或者,我的皮肤,我的家庭,或者,我们的世界.....(或者,世界之外....)。虚拟分层包括两层含义,一是虚拟,而是分层,虚拟指的是类似分形的我中有你,你中有我的一个总体结构,而分层是一个部分的,低耦合高内聚的组成实体,它对上层屏蔽下层,使用下层的接口服务为上层提供统一接口服务。
按照这个思想,多线程就有运而生了,现在已经有了:硬件(cpu等)-〉操作系统-〉进程,的层次关系了,而且在操作系统的管理之下,进程运行在操作系统提供的虚拟cpu上,同样的道理,这里把虚拟cpu当作真正的cpu的话,就可以在这个cpu(虚拟的)上实现多道程序设计了,进程作为管理者,再向上抽象一层,这就是线程!这里的进程成了属于它的线程的“操作系统”,每个线程都认为自己拥有整个虚拟cpu,所有线程实际上共享这个虚拟cpu。截至目前我 们的层次化表示为:硬件cpu-〉操作系统-〉进程-〉线程;而虚拟化表示为:硬件cpu(操作系统)-〉虚拟cpu(进程)-〉线程。这么看来,继续下 去是可行的,我们可以再进一步抽象,进程可以提供一个虚拟虚拟cpu,从学术意义上,这是很优美的,但是从技术上,却是没有意义,因为我们没有理由这么做,学术上往往从和谐和美学角度分析问题,但是在技术上,做一件事必须有一个可实施的非空洞理由!往往很多成果都是现有了理论,然后当那个理由很充分的时 候,技术上的对应物就出现了,上面谈的都是理论的东西,那么促使多道程序设计和线程出现的那个理由到底是什么呢?
最开始的时候,应用计算机就是为了计算一些数值运算,退一步说就是给它一个1,给它一个+,再给它一个1,问它结果等于几,诸如此类的问题,那么可以直接 用硬连线实现,随着半导体的发展,计算机的运算性能不断提高,仅仅用于计算大大浪费,所以就用它来做很多的事情,从而产生了批处理系统,但是一个时间做一件事情也不好,于是,多道程序设计就出现了,当时多道程序设计刚起步,人们的想法还只是很简单的隔离进程的思想,进程间通信的代价很大,就像不同机器的通 信差不多,随着时间的推移以及多道程序设计的进一步完善,加之人们共享概念的生成,很自然的需要在不同进程之间共享一些资源,所以对进程间通信提出了挑战,最终促使了多线程的产生......
基本概念我们都明白了,那么现在你能理解现实中的系统了吗?能理解intel的VT技术吗?实际上全是虚拟分层思想的套用,intel为了在其处理器上并发运行不同操作系统,那么必须在硬件和操作系统之间加一层管理层,这就是VT-xxx技术了。
注意,我上面的讨论中,丝毫没有提到存储器和IO,其实,计算和存储两大部分只是冯诺依曼机器的模型,很多并行机并非那样,如果非要说说冯诺依曼机器和虚拟分层思想的对应,那么就只有两点需要注意,一个是计算,一个是存储,负责计算的是进程或线程,负责存储的就是另一大部分了---虚拟存储器,文件和外设 IO,而虚拟存储器也是一个分层的东西。而IO为何一般不向上层抽象呢?
我们上面讨论虚拟机思想的时候说到了抽象,操作系统把cpu指令都抽象给了进程,那为什么没有把IO给进城呢?每当进程需要IO服务时,必须请求操作系统 系统调用。因为在冯诺依曼机中cpu是核心,一切控制的核心,所有控制序列都是从cpu发起的,cpu的核心就是计算,而IO设备并不具备这样的机制,形象一点说,不管是多道程序设计还是多线程都是cpu提供的机制,操作系统提供的策略,执行一条指令,cpu中的硬件逻辑(寄存器上下文)知道这个指令属于 哪个进程或者线程,而且也控制好了互斥等等,然而IO外设则不然,你发给它一条指令,它只会傻乎乎的执行,它并没有控制逻辑,它只有要么I,要么O接口, 控制逻辑是外设相关的,比如你把一个字符串写到ntfs格式磁盘和写道xfs格式磁盘,或者写道el1000网卡的格式是不一样的,
外设内在地并 不支持多进程多线程和控制逻辑,所以这么直接在进程(线程)上下文执行IO是很危险的,因此,外设不能简单地抽象给进程。我个人认为,把cpu和外设同等 对待,在外设上也加入复杂的控制逻辑,就可以将外设抽象给进程了,但是那样硬件的设计就复杂了,外设的多样性使得提供统一的指令级别的接口变得不可能,而且也违背了机制策略分离的原则(cpu提供那么多的控制功能恰恰没有问题,因为它的任务就是控制计算,而计算很大程度上接口是很容易统一的)。于是在各个处理器指令集里,io指令被称为敏感指令,而还有一些指令是无论如何,进程都不能触及的,这就是cpu控制进程或线程的特权指令。
前面说了那么多,同时又闲扯了上面这一段,还是回到多线程,我们真的该用多线程吗?我们符合多线程带来实惠的条件吗?不少人为了展示自己多懂编程,动不动就pthread_create,包括我也一样,当你真正理解多线程以后,看过多线程的实现以后,你会不禁一叹!多线程建立销毁的开销,多线程切换的开销,多线程互斥的开销,你富裕到足够消费这些的程度了吗?如果你仅仅拥有单cpu,那么对于cpu密集型的计算只会徒增复杂性和开销而已,到头来程序更 慢,对于io密集型的计算,多线程倒是个好主意,因为一个在等io的时候另一个可以进行计算,单cpu上,线程就是时间片。考虑一下在只有一个经理的情况下,他要处理5个文件,如果他一心一意处理文件,没有别的打扰,而且他从不停顿的话,是让一个人把5个文件一下子全部拿来好呢,还是5个人每人拿一份文 件,一次进去一个人送一份文件,等经理处理完后让他出去叫另一个拿文件进来好呢?计算机里面的东西在现实中都有相应的模型,比如找零钱问题,处理器流水线....如果你在现实世界没有找到一个模型或者说和现实世界的做法背道而驰,而把它引入计算机系统的话,那将不是一个好的主意!
最后推荐两篇文章,本来我准备写点相关的东西呢,后来没有时间了,于是共享一把别人的资源:
操作系统系列之概述 (http://fixopen.javaeye.com/blog/27850)
多线程是个不靠谱的东西(http://www.javaeye.com/topic/189994)
原文链接: https://blog.csdn.net/dog250/article/details/5302718
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;
也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/410749
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!