Linux中進程和線程的開銷基本一樣啊,為什麼還要多線程呢?

多進程優點:不互相影響,有利於水平參差不齊的程序員合作。

多線程優點:創建速度快,數據共享(進程間數據共享麻煩)

歷史原因:以前操作系統沒有native線程,後來cpu還特地增加了線程寄存器,才使得線程的切換速度能很快。


首先我想不到任何一個應用有合理的理由來開30個以上的線程(進程)(這裡指普通的 4 核心機器。如果機器有64個核心,那麼開64個線程是很正常的),也想不到有一個應用是不斷地創建和銷毀進程(線程)的,這些都是很勺的編程方法

在上麵條件的限制下,線程和進程的時間和空間開銷確實是差不多的,優化措施不建議從兩者的開銷這個角度考慮

兩個模型的差異在於, 進程更安全,一個進程完全不會影響另外的進程。所以這也是 unix 哲學裡推薦的編程方法;但是進程間通信比線程間通信的性能差很多,尤其是,如果這個是系統的關鍵部分,而又有大量數據的時候,所有的進程間通信方法都比線程間的通信慢很多

所以通常情況下推薦多進程程序,就像 nginx,一個 master 多個 worker,進程間只進行有限的通信(傳遞命令而非數據)

多線程的典型例子是 unbound,一個開源的遞歸 dns 伺服器。它使用線程的理由也很充分:程序需要不停地向後方的授權 dns 請求數據,並傳回給前方的模塊。這個數據通信量大,性能要求又高,所以必須用多線程,如果是多個進程,那就要慢許多了


Linux中的線程上下文切換比進程切換開銷要小很多,因為不需要切換頁表、刷新TLB。

===================以上回答是錯的!!!=====================

2017.8.8更新:之前的回答有問題有誤,糾正一下,應該來說二者的切換開銷沒有太大差別。本質上進程/線程在Linux內核實現上都是Task(或者叫Thread,在內核里是同一個東東),只不過同源多線程對應的Task共享的東西多一些(最主要是地址空間)。所以即便是多線程切換,頁表也還是要切換的,只不過頁表內容相同而已;同樣,對於多線程切換,TLB該刷還是要刷的,因為對於CPU來講多線程與多進程一樣,都有不同的標識和不同的上下文,為了保證一致性,TLB刷新就省不了。


首先,前提「Linux中進程和線程的開銷基本一樣」是錯的。創建進程慢10倍。

其次,就算一啟動就創建全部進程/線程,有些編程任務更適合多線程,比如聊天伺服器。


關於這個問題,可參見我在多線程帖子裡面說過的,最主要的是 Windows 下的編程習慣問題。

另外來說,開銷這個問題存在誤解。因為開銷分多方面。時間開銷跟空間開銷。

就時間開銷而言,Linux 下創建進程跟線程差不多,事實上創建線程的時間開銷略微大一點點。

就空間開銷而言,Linux 下創建進程總是有開銷的,而且顯然會略大於線程。

如果你需要不斷的創建進程,做完事情之後,銷毀進程,然後做下一件事情的時候再創建進程,做完事情之後銷毀,進程數量在數百以內的級別,那麼進程跟線程的效率是差不多的。這種情況下推薦使用進程。

如果你需要創建極大量的進程(成千上萬這個級別),此時的效率跟創建大量的線程還是會有一定差別。如果這個差別已經大到了影響你的應用,那麼你可以試著考慮使用線程。

一般來說,我認為這個差別不大的情況下,使用進程仍然更可取,因為程序的穩定性健壯性是第一位的,而性能與資源方面的開銷往往可以通過提升伺服器能力或者增加伺服器解決。


直接fork 和pthread_create 比較,創建線程快3~5倍,

當進程已經分配幾十M、幾百M甚至幾G的內存,這時候fork和pthread_create比較,創建線程 要快幾十倍。

另外線程間因為地址空間共享,通信比較簡單,也只是簡單,考慮到緩存一致性,性能上的優勢並不像想像的那麼大。主要是給懶人用的。

另外的確有些場景非常適合多線程,比如陳碩大神提到的例子。


  • 數據共享
  • 繼續 Windows 下的多線程編程習慣


先不談開銷的問題,假設你說的成立。

在編程的時候選擇進程和線程,很關鍵的一點應該是內存空間是否共享的,涉及到通信機制的問題,比如IPC通常是socket、管道、共享內存api等,而線程間通信則還可以基於大家都直接能否訪問的內存空間。

回到開銷的問題(簡單地從理論上看,實測數據有可能差不多,我沒調研過): 1. 線程進程的區別主要在於一些資源是否需要新建一份,比如文件系統信息、信號處理信息等。有一些東西(已知內存塊)已經通過COW優化,所以進程和線程這方面開銷區別應該不大。2.上下文切換,寄存器、棧等是必須的,線程不需要切換頁面映射。

最後,常聽說POSIX線程的定義就是比進程輕量的,從這一點上來看,直覺線程更加輕量也是可以理解的。


Linux其實本事沒有線程的概念,只是為了迎合開發者的需要而使用了一個所謂輕量級進程(POSIX線程),你從這兩者區別也可以發現,輕量級進程最大的用途在於可以共享一些資源,如地址空間,打開文件
。所以,事實上Linux實現多線程應用程序的方式就是用輕量級進程來代替線程


[linux內核設計與實現]

進程/線程機制是編程技術中常用的一種抽象概念,在多個處理單元上它能保證真正的並行處理。傳統OS原理,相較於進程,線程被抽象成一種耗費較少資源,運行迅速的執行單元。但Linux不像Windows或Solaris,它沒有線程概念,線程當做進程實現了。Linux進程本身已經足夠輕量,線程是進程間共享資源的手段。


雖然Linux中線程沒有單獨的數據結構,進程和線程差別也不大,但是進程在切換的時候要切換地址空間,而線程在切換的時候判斷一下是不是在一個進程組,如果屬於一個進程組,只是切換一下上下文而已,所以開銷要小的多。


Create Process &>&> Create Thread

Process Context Switch &> Thread Context Switch


建議看下linux內核之類的書 會講到進程和線程是如何創建的;linux創建進程、線程都是同一個數據結構,不過多線程共享進程的很多資源:比如地址空間、fd,而進程需要寫時創建,開銷肯定大些;當然多進程 編程安全,可靠,但進程間通信不如多線程方便。 而且看業務場景,比如mobi遊戲 不同戰鬥就開多線程,因為要頻繁創建,釋放;不同戰鬥間不會有同步問題。


linux下fork的叫進程

clone的叫輕量級進程

pthread叫線程

進程和輕量級進程的區別僅僅在於前者不共享資源,後者共享資源,進程和輕量級進程都有一個task_struct,操作系統是可以感知的,也就是可以由核心態的調度器來調度

pthread只是用戶態的線程庫,操作系統根本不知道有這麼個東西,調度是由用戶態的調度器來調度的

資料一搜一大把,百度一下就好~


我補充下,kernel 3.0後線程的機制出現了一些變化,做了一些優化,和各位說的「linux沒有線程」的時代不一樣了。


最近正在看操作系統,下面內容摘自:《現代操作系統第三版》

  • 在許多系統中,創建一個線程較創建一個進程要快10~100倍。

  • 若多個線程都是CPU密集型的,那麼並不能獲得性能上的增強,如果存在大量的計算與大量的I/O處理,擁有多個線程允許這些活動彼此重疊進行,從而加快應用程序執行的速度。

  • 在多CPU系統中,多線程是有益的,在這樣的操作系統中,真正的並行有了實現的可能。

我自己的理解:

  • 進程越多,如果成千上萬級別,CPU將在上下文切換上花費極多的時間空間代價。

  • 線程是共享內存,進程不是,進程間通信代價比線程間通信代價高得多。


linux下系統創建線程要比創建進程的開銷小得多。 內核無需單獨複製進程的內存空間或文件描述符等等,這就節省了大量的CPU時間,也節省很多內在空間。使用多線程,無需使用繁瑣的IPC和其它複雜的通信機制。


推薦閱讀:

為什麼Windows中文默認使用GB18030而不是UTF-8?
win10總是很快自動休眠怎麼解決?
為什麼Windows XP 經歷了5年微軟才推出下一代 Windows?
如何看待很多PC用戶在一段時間之後將win8/8.1刷回win7?
為什麼「回收站」可以「永存」於 Windows 系統中?

TAG:操作系統 | Linux |