多线程

来源:互联网 发布:模仿游戏完整解析 知乎 编辑:程序博客网 时间:2024/06/07 10:03
作者:pansz
链接:https://www.zhihu.com/question/19901763/answer/13299543
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

这么解释问题吧:

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 为多核的情况下,多线程在性能上不如多进程。

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


同样以吃饭举例子,假设很多人需要吃饭吃饭,桌子不够,那么桌子就是紧缺资源。单线程就是整个餐厅只有一个单人桌,这个人吃完了,下一个人轮上。但大餐馆用的可能是八仙桌(好吧我比较喜欢这种古代的方正桌子),同时能容纳八个人吃饭,这就是多线程:从一次一个变成了一次多个或者多次多个。如何安排吃饭顺序对程序员来说是个巨大的挑战,主要问题在于对资源-桌子的安排上,举例说明:
1.死锁-大家都在等着吃饭,但需要特定条件才能开吃:桌一等着桌二的碗,桌二等着桌三的筷子,桌三呢,等着桌一的勺。于是这三桌就都不能吃饭。
2.非原子变量更新-空闲桌子的数字是要加以保护的,类似于特定人员才能修改,假如没有保护,空桌子一会儿是四个,一会儿是五个,最终的数字往往是不正确的,服务员要被玩死-这就是多线程的加锁操作。
还有其他几种,就不多说了,多线程的调度和使用是一个坑,是否能用好是程序员水平高低的一个标志。


作者:韩葆-逸松
链接:https://www.zhihu.com/question/19901763/answer/92891514
来源:知乎
著作权归作者所有,转载请联系作者获得授权。
原创粉丝点击