学鬼

多线程和多进程的区别

Linux内核实际上是不区分进程和线程的,它们都是用的task_struct结构体,Linux上的线程是LWP,即轻量级进程。创建进程的fork()函数和创建线程的clone()函数内核底层都调用了do_fork()函数。对于线程来说,使用了CLONE_VM(共享内存空间)、CLONE_FS(共享文件系统信息)、CLONE_FILES(共享文件描述符表)、CLONE_SIGHAND(共享信号处理函数)等属性,所以线程是共享地址空间的。而创建进程调用do_fork()则不会使用任何共享属性,进程拥有独立的运行环境。不过由于fork()采用写时拷贝,所以创建进程开销也有一定的优化。

进程切换也比线程开销大。因为进程切换时,不仅要保存相关寄存器和栈的信息,而且要更新CR3寄存器,也就是切换页表,刷新TLB,而且往往伴随着页面调度,因为进程的数据段代码段都要换出去,以便将要执行的进程内容换进来。而线程由于共享地址空间,切换是只需保存线程的上下文(即相关寄存器和栈的信息)就好了。

同样由于共享地址空间,同一进程的不同线程之间很容易共享数据,而进程则需要IPC机制来通信。不过,由于不共享地址空间,进程容错性更好一些,一个进程挂掉不会导致系统崩溃。多线程在多核架构下容易发生伪共享现象(false sharing),由于数据共享,一个CPU修改了数据,其余CPU的cache全部失效并重新加载。而多进程共享的内存是程序员控制的,一般不会出现伪共享。

多线程适合与SMP架构,多进程还可以扩展到多台机器。

如下表:

对比维度 多进程 多线程 总结
数据同步、共享 数据共享复杂,需要用IPC;数据是分开的,同步简单 因为共享进程数据,数据共享简单,但也是因为这个原因导致同步复杂 各有优势
内存CPU 内存占用多,切换复杂,CPU利用率低 占用内存少,切换简单,CPU利用率高 线程占优
创建销毁、切换 创建销毁、切换复杂,速度慢 创建销毁、切换简单,速度很快 线程占优
编程、调试 编程简单,调试简单 编程复杂,调试复杂 进程占优
可靠性 进程间不会相互影响 一个线程挂掉导致整个进程挂掉 进程占优
分布式 适用于多核、多机分布式;可扩展多台机器 适用于多核分布式

如何选择?

  1. 需要频繁创建销毁优先用线程
  2. 需要进程大量计算优先用线程(耗费CPU,切换频繁)
  3. 强相关的处理用线程,弱相关的处理用进程(也就是数据交换多的用线程)
  4. 可能要扩展到多机分布的用进程,多核分布用线程

参考:
1. 有关linux下多进程与多线程的区别总结
2. 进程切换
3. 多线程伪共享(false sharing)问题分析
4. Linux 下多线程和多进程程序的优缺点,各自适合什么样的业务场景?

posted on 2017-02-27 12:28  学鬼  阅读(301)  评论(0编辑  收藏  举报

导航