Linux中的线程上下文切换比进程切换开销要小很多,因为不需要切换页表、刷新TLB。
关于这个问题,可参见我在多线程帖子里面说过的,最主要的是 Windows 下的编程习惯问题。
另外来说,开销这个问题存在误解。因为开销分多方面。时间开销跟空间开销。
就时间开销而言,Linux 下创建进程跟线程差不多,事实上创建线程的时间开销略微大一点点。
就空间开销而言,Linux 下创建进程总是有开销的,而且显然会略大于线程。
如果你需要不断的创建进程,做完事情之后,销毁进程,然后做下一件事情的时候再创建进程,做完事情之后销毁,进程数量在数百以内的级别,那么进程跟线程的效率是差不多的。这种情况下推荐使用进程。
如果你需要创建极大量的进程(成千上万这个级别),此时的效率跟创建大量的线程还是会有一定差别。如果这个差别已经大到了影响你的应用,那么你可以试着考虑使用线程。
一般来说,我认为这个差别不大的情况下,使用进程仍然更可取,因为程序的稳定性健壮性是第一位的,而性能与资源方面的开销往往可以通过提升服务器能力或者增加服务器解决。
另外来说,开销这个问题存在误解。因为开销分多方面。时间开销跟空间开销。
就时间开销而言,Linux 下创建进程跟线程差不多,事实上创建线程的时间开销略微大一点点。
就空间开销而言,Linux 下创建进程总是有开销的,而且显然会略大于线程。
如果你需要不断的创建进程,做完事情之后,销毁进程,然后做下一件事情的时候再创建进程,做完事情之后销毁,进程数量在数百以内的级别,那么进程跟线程的效率是差不多的。这种情况下推荐使用进程。
如果你需要创建极大量的进程(成千上万这个级别),此时的效率跟创建大量的线程还是会有一定差别。如果这个差别已经大到了影响你的应用,那么你可以试着考虑使用线程。
一般来说,我认为这个差别不大的情况下,使用进程仍然更可取,因为程序的稳定性健壮性是第一位的,而性能与资源方面的开销往往可以通过提升服务器能力或者增加服务器解决。
首先,前提「Linux中进程和线程的开销基本一样」是错的。创建进程慢10倍。
其次,就算一启动就创建全部进程/线程,有些编程任务更适合多线程,比如聊天服务器。
其次,就算一启动就创建全部进程/线程,有些编程任务更适合多线程,比如聊天服务器。
首先我想不到任何一个应用有合理的理由来开30个以上的线程(进程)(这里指普通的 4 核心机器。如果机器有64个核心,那么开64个线程是很正常的),也想不到有一个应用是不断地创建和销毁进程(线程)的,这些都是很勺的编程方法
在上面条件的限制下,线程和进程的时间和空间开销确实是差不多的,优化措施不建议从两者的开销这个角度考虑
两个模型的差异在于, 进程更安全,一个进程完全不会影响另外的进程。所以这也是 unix 哲学里推荐的编程方法;但是进程间通信比线程间通信的性能差很多,尤其是,如果这个是系统的关键部分,而又有大量数据的时候,所有的进程间通信方法都比线程间的通信慢很多
所以通常情况下推荐多进程程序,就像 nginx,一个 master 多个 worker,进程间只进行有限的通信(传递命令而非数据)
多线程的典型例子是 unbound,一个开源的递归 dns 服务器。它使用线程的理由也很充分:程序需要不停地向后方的授权 dns 请求数据,并传回给前方的模块。这个数据通信量大,性能要求又高,所以必须用多线程,如果是多个进程,那就要慢许多了
在上面条件的限制下,线程和进程的时间和空间开销确实是差不多的,优化措施不建议从两者的开销这个角度考虑
两个模型的差异在于, 进程更安全,一个进程完全不会影响另外的进程。所以这也是 unix 哲学里推荐的编程方法;但是进程间通信比线程间通信的性能差很多,尤其是,如果这个是系统的关键部分,而又有大量数据的时候,所有的进程间通信方法都比线程间的通信慢很多
所以通常情况下推荐多进程程序,就像 nginx,一个 master 多个 worker,进程间只进行有限的通信(传递命令而非数据)
多线程的典型例子是 unbound,一个开源的递归 dns 服务器。它使用线程的理由也很充分:程序需要不停地向后方的授权 dns 请求数据,并传回给前方的模块。这个数据通信量大,性能要求又高,所以必须用多线程,如果是多个进程,那就要慢许多了
Linux其实本事没有线程的概念,只是为了迎合开发者的需要而使用了一个所谓轻量级进程(POSIX线程),你从这两者区别也可以发现,轻量级进程最大的用途在于可以共享一些资源,如地址空间,打开文件 。所以,事实上Linux实现多线程应用程序的方式就是用轻量级进程来代替线程 。
linux中线程是通过clone来实现的,实质上linux是没有线程的,线程与进程创建的速度差异在取得资源上,进程取得资源需要申请所有的,并调入内存中。而线程是共享的,只需要申请属于自己的少量的私有资源,明显时间就会短很多
- 数据共享
- 继续 Windows 下的多线程编程习惯
先不谈开销的问题,假设你说的成立。
在编程的时候选择进程和线程,很关键的一点应该是内存空间是否共享的,涉及到通信机制的问题,比如IPC通常是socket、管道、共享内存api等,而线程间通信则还可以基于大家都直接能否访问的内存空间。
回到开销的问题(简单地从理论上看,实测数据有可能差不多,我没调研过): 1. 线程进程的区别主要在于一些资源是否需要新建一份,比如文件系统信息、信号处理信息等。有一些东西(已知内存块)已经通过COW优化,所以进程和线程这方面开销区别应该不大。2.上下文切换,寄存器、栈等是必须的,线程不需要切换页面映射。
最后,常听说POSIX线程的定义就是比进程轻量的,从这一点上来看,直觉线程更加轻量也是可以理解的。
在编程的时候选择进程和线程,很关键的一点应该是内存空间是否共享的,涉及到通信机制的问题,比如IPC通常是socket、管道、共享内存api等,而线程间通信则还可以基于大家都直接能否访问的内存空间。
回到开销的问题(简单地从理论上看,实测数据有可能差不多,我没调研过): 1. 线程进程的区别主要在于一些资源是否需要新建一份,比如文件系统信息、信号处理信息等。有一些东西(已知内存块)已经通过COW优化,所以进程和线程这方面开销区别应该不大。2.上下文切换,寄存器、栈等是必须的,线程不需要切换页面映射。
最后,常听说POSIX线程的定义就是比进程轻量的,从这一点上来看,直觉线程更加轻量也是可以理解的。
[linux内核设计与实现]
进程/线程机制是编程技术中常用的一种抽象概念,在多个处理单元上它能保证真正的并行处理。传统OS原理,相较于进程,线程被抽象成一种耗费较少资源,运行迅速的执行单元。但Linux不像Windows或Solaris,它没有线程概念,线程当做进程实现了。Linux进程本身已经足够轻量,线程是进程间共享资源的手段。
进程/线程机制是编程技术中常用的一种抽象概念,在多个处理单元上它能保证真正的并行处理。传统OS原理,相较于进程,线程被抽象成一种耗费较少资源,运行迅速的执行单元。但Linux不像Windows或Solaris,它没有线程概念,线程当做进程实现了。Linux进程本身已经足够轻量,线程是进程间共享资源的手段。
我补充下,kernel 3.0后线程的机制出现了一些变化,做了一些优化,和各位说的“linux没有线程”的时代不一样了。
建议看下linux内核之类的书 会讲到进程和线程是如何创建的;linux创建进程、线程都是同一个数据结构,不过多线程共享进程的很多资源:比如地址空间、fd,而进程需要写时创建,开销肯定大些;当然多进程 编程安全,可靠,但进程间通信不如多线程方便。 而且看业务场景,比如mobi游戏 不同战斗就开多线程,因为要频繁创建,释放;不同战斗间不会有同步问题。
最近正在看操作系统,下面内容摘自:《现代操作系统第三版》
- 在许多系统中,创建一个线程较创建一个进程要快10~100倍。
- 若多个线程都是CPU密集型的,那么并不能获得性能上的增强,如果存在大量的计算与大量的I/O处理,拥有多个线程允许这些活动彼此重叠进行,从而加快应用程序执行的速度。
- 在多CPU系统中,多线程是有益的,在这样的操作系统中,真正的并行有了实现的可能。
- 进程越多,如果成千上万级别,CPU将在上下文切换上花费极多的时间空间代价。
- 线程是共享内存,进程不是,进程间通信代价比线程间通信代价高得多。
linux下系统创建线程要比创建进程的开销小得多。 内核无需单独复制进程的内存空间或文件描述符等等,这就节省了大量的CPU时间,也节省很多内在空间。使用多线程,无需使用繁琐的IPC和其它复杂的通信机制。