最近我听到一些人说,在Linux中,使用进程几乎总是比使用线程更好,因为Linux在处理进程方面非常高效,而且与线程相关的问题太多了(比如锁)。然而,我对此持怀疑态度,因为在某些情况下,线程似乎可以带来相当大的性能提升。
因此,我的问题是,当遇到线程和进程都可以很好地处理的情况时,我应该使用进程还是线程?例如,如果我正在编写一个web服务器,我应该使用进程还是线程(或组合)?
最近我听到一些人说,在Linux中,使用进程几乎总是比使用线程更好,因为Linux在处理进程方面非常高效,而且与线程相关的问题太多了(比如锁)。然而,我对此持怀疑态度,因为在某些情况下,线程似乎可以带来相当大的性能提升。
因此,我的问题是,当遇到线程和进程都可以很好地处理的情况时,我应该使用进程还是线程?例如,如果我正在编写一个web服务器,我应该使用进程还是线程(或组合)?
当前回答
更复杂的是,还有线程本地存储和Unix共享内存。
Thread-local storage allows each thread to have a separate instance of global objects. The only time I've used it was when constructing an emulation environment on linux/windows, for application code that ran in an RTOS. In the RTOS each task was a process with it's own address space, in the emulation environment, each task was a thread (with a shared address space). By using TLS for things like singletons, we were able to have a separate instance for each thread, just like under the 'real' RTOS environment.
共享内存(显然)可以为您带来让多个进程访问相同内存的性能优势,但代价是必须正确地同步进程。一种方法是让一个进程在共享内存中创建一个数据结构,然后通过传统的进程间通信(如命名管道)向该结构发送句柄。
其他回答
其他人讨论了这些考虑因素。
也许重要的区别是,在Windows中,与线程相比,进程是沉重和昂贵的,而在Linux中,差异要小得多,所以等式在不同的点上平衡。
在大多数情况下,我更喜欢进程而不是线程。 当您有一个相对较小的任务(每个划分的任务单元占用的进程开销>>时间),并且需要在它们之间共享内存时,线程可能会很有用。想象一个大数组。 另外(离题),请注意,如果您的CPU利用率是100%或接近100%,那么多线程或处理将没有任何好处。(事实上情况会更糟)
Linux(实际上还有Unix)为您提供了第三种选择。
选项1 -流程
创建一个独立的可执行文件来处理应用程序的某些部分(或所有部分),并为每个进程分别调用它,例如,程序运行自己的副本来委托任务。
选项2 -线程
创建一个独立的可执行文件,它由一个线程启动,并创建额外的线程来执行一些任务
选项3 -分叉
仅在Linux/Unix下可用,这有点不同。fork进程实际上是拥有自己地址空间的进程——子进程(通常)无法影响其父进程或兄弟进程的地址空间(不像线程)——因此您获得了额外的健壮性。
但是,内存页不是复制的,它们是写时复制的,因此通常使用的内存比您想象的要少。
考虑一个web服务器程序,它包含两个步骤:
读取配置和运行时数据 服务页面请求
如果您使用线程,第1步将完成一次,第2步将在多个线程中完成。如果您使用“传统”流程,那么每个流程都需要重复步骤1和步骤2,存储配置和运行时数据的内存也需要重复。如果您使用fork(),那么您可以执行第1步,然后fork(),将运行时数据和配置保留在内存中,不受影响,不复制。
所以实际上有三种选择。
我不得不同意你所听到的。当我们对我们的集群(xhpl等)进行基准测试时,我们总是通过进程而不是线程获得明显更好的性能。< /轶事>
如果你需要共享资源,你真的应该使用线程。
还要考虑这样一个事实:线程之间的上下文切换比进程之间的上下文切换代价要小得多。
我认为没有理由明确地使用单独的进程,除非你有一个很好的理由这样做(安全,经过验证的性能测试,等等……)