聚宝小猪

博客园 首页 新随笔 联系 订阅 管理

这么解释问题吧:

1。单进程单线程:一个人在一个桌子上吃菜。
2。单进程多线程:多个人在同一个桌子上一起吃菜。
3。多进程单线程:多个人每个人在自己的桌子上吃菜。

多线程的问题是多个人同时吃一道菜的时候容易发生争抢,例如两个人同时夹一个菜,一个人刚伸出筷子,结果伸到的时候已经被夹走菜了。。。此时就必须等一个人夹一口之后,在还给另外一个人夹菜,也就是说资源共享就会发生冲突争抢。


1。对于 Windows 系统来说,【开桌子】的开销很大,因此 Windows 鼓励大家在一个桌子上吃菜。因此 Windows 多线程学习重点是要大量面对资源争抢与同步方面的问题。


2。对于 Linux 系统来说,【开桌子】的开销很小,因此 Linux 鼓励大家尽量每个人都开自己的桌子吃菜。这带来新的问题是:坐在两张不同的桌子上,说话不方便。因此,Linux 下的学习重点大家要学习进程间通讯的方法。

--
补充:有人对这个开桌子的开销很有兴趣。我把这个问题推广说开一下。

开桌子的意思是指创建进程。开销这里主要指的是时间开销。
可以做个实验:创建一个进程,在进程中往内存写若干数据,然后读出该数据,然后退出。此过程重复 1000 次,相当于创建/销毁进程 1000 次。在我机器上的测试结果是: 
UbuntuLinux:耗时 0.8 秒 
Windows7:耗时 79.8 秒 
两者开销大约相差一百倍。

这意味着,在 Windows 中,进程创建的开销不容忽视。换句话说就是,Windows 编程中不建议你创建进程,如果你的程序架构需要大量创建进程,那么最好是切换到 Linux 系统。

大量创建进程的典型例子有两个,一个是 gnu autotools 工具链,用于编译很多开源代码的,他们在 Windows 下编译速度会很慢,因此软件开发人员最好是避免使用 Windows。另一个是服务器,某些服务器框架依靠大量创建进程来干活,甚至是对每个用户请求就创建一个进程,这些服务器在 Windows 下运行的效率就会很差。这"可能"也是放眼全世界范围,Linux 服务器远远多于 Windows 服务器的原因。

--
再次补充:如果你是写服务器端应用的,其实在现在的网络服务模型下,开桌子的开销是可以忽略不计的,因为现在一般流行的是按照 CPU 核心数量开进程或者线程,开完之后在数量上一直保持,进程与线程内部使用协程或者异步通信来处理多个并发连接,因而开进程与开线程的开销可以忽略了。--???

另外一种新的开销被提上日程:核心切换开销。

现代的体系,一般 CPU 会有多个核心,而多个核心可以同时运行多个不同的线程或者进程。

当每个 CPU 核心运行一个进程的时候,由于每个进程的资源都独立,所以 CPU 核心之间切换的时候无需考虑上下文。

当每个 CPU 核心运行一个线程的时候,由于每个线程需要共享资源,所以这些资源必须从 CPU 的一个核心被复制到另外一个核心,才能继续运算,这占用了额外的开销。换句话说,在 CPU 为多核的情况下,多线程在性能上不如多进程。

因而,当前面向多核的服务器端编程中,需要习惯多进程而非多线程。

 

==================================================================================================================================================

很多人答案说的是操作系统提供的多进程而不是单个程序内的多线程。 

多线程使得程序内部可以分出多个线程来做多件事情,而不会造成程序界面卡死。比如迅雷等多线程下载工具就是典型的多线程。一个下载任务进来,迅雷把文件平分成10份,然后开10个线程分别下载。这时主界面是一个单独的线程,并不会因为下载文件而卡死。而且主线程可以控制下属线程,比如某个线程下载缓慢甚至停止,主线程可以把它强行关掉并重启另外一个线程。 

另外就是一些程序的打印功能,比如记事本、Adobe Reader,打印的时候就只能打印,无法在主界面进行操作,而Word就有“后台打印”的功能,点了打印命令之后,还可以回到主界面进行修改、保存等操作。 

另外多线程除了并行完成一些任务以外,还有生产者-消费者模式。比如Windows命令行下在某个硬盘根目录执行一个"dir/s | more"命令,前一条显示硬盘里的所有文件,要执行很久才能执行得完,后面那条命令会把前面命令的输出分屏显示出来。但是执行整条命令时,会立刻有显示,也就是说,前面一条命令输出满一页内容到缓冲区,more命令就把缓冲区封死了,等用户敲了一个键显示下一屏的时候,more命令把缓冲区的内容取出并清空,前面的命令才能输出下一屏到缓冲区。这样的多线程使得整条命令不用等待前面的命令全部执行完才能执行下一条命令。 

多线程和多进程的区别。平常指的多进程是操作系统下同时运行多个进程,比如Word和Excel同时打开,并且可以并行地同时执行一些操作。这种多进程和多线程没什么好比较的。可以比较的是同一个程序里的多线程和多进程。 

多线程因为在同一个进程里,所以可以共享内存和其他资源,比如迅雷里10个线程一齐下载一个文件,这个文件是由进程打开的,然后10个线程都可以往里写入东西。如果是10个进程就不行了,操作系统不允许一个文件由两个进程同时写入。另外,Chrome就是一个典型的多进程程序,里面每个标签页、扩展、插件都是单独的进程,各自独占资源,相互隔离,一个进程出错死掉只会影响一个页面或者插件,再也不会出现Flash插件出错崩溃导致整个浏览器崩溃的情况了。

 

================================================================================================================================================


1. 多核心意味着有两个或两个以上的独立实体中央处理单元,两个单元可以各自独立地运行不同指令,是真正的并行。

2. 但凡写过程序就应该知道任务背景不同,多线程的效果也不同,如果有IO、网络的等待,两个核心你开两个线程,那线程一旦阻塞了,这个核心就闲置了。

3. 超线程,就是如果两个线程在同一时间的指令使用的流水线单元(像分支预测器)不一样, 则一个核可以同时处理。但理想情况总是较少的,所以比起真正的两个核心还是差得远。万一发生资源互抢的情形时,整体性能反而会下降。

4. IOCP示例往往开CPU数量*2+2或者CPU数量*2个线程,可能有像第2点所说的避免闲置的作用,不过如果线程是计算密集的,开得线程多了,反而会把资源浪费在上下文切换上。

总之:
在单核心下,为了实现伪多任务,要把一堆时间片分给不同任务,所以多线程除了有IO、网络等的等待,在实质很难提高效率;
在多核心下,多线程一般都可以提高效率的,但具体设计多少个线程还是得看具体情况;
至于超线程,目前效果并不好,建议编写程序时参考Intel系统编程指南,还有这篇文章:超线程技术适合什么样的程序?,据说在网络服务器上效果还是有的。

现在搞异步、协程的比较多,题主也不妨看下。
 
=================================================================================================================================================
说到效率,那假设前提计算资源相比程序是瓶颈一方,如果线程之间都并行,相互之间没有关系,当然是跟CPU等数量最好(超线程不谈),什么Cache不中之类根本不需要考虑,否则硬件体系结构肯定就不过关。那下一步就是操作系统调度的问题,成熟的操作系统在应对这种最简单的情形也肯定不会让CPU闲在那里。
如果超过了CPU数量,显然需要多余的调度代码来执行,而总的计算能力不会增加,那么比不过相等的情形。
复杂一点是线程之间有同步/竞争关系,那么考虑到cache不中的等情形,就很难说能提高多少,但绝大多数需要足够运算能力的情形下,也基本可以认为等同是最佳的。除非故意把代码分割成粒度极小的执行单元,但想到调度也可能早已成为性能瓶颈了,这种故意劣化cpu性能的代码也很难在真实世界中上演。
实际上,在目前主流程序设计语言中,因为缺少较好的协程同步机制,而对于异步代码大多数情况有觉得用多线程写起来更加容易,即要不很难做到任务并行划分,要不就开大量线程,很少人会想到要做到恰好等同cpu数量。同时极度消耗计算资源的时候也是很少的,所以大多数情形下这也不是一个问题,搞并行高性能计算才需要关心一下。
posted on 2015-10-08 22:46  聚宝小猪  阅读(132)  评论(0编辑  收藏  举报