維度
多程序多執行緒
總結資料共享、同步
資料是分開的,共享複雜,需要用ipc;同步簡單
多執行緒共享程序資料,共享簡單;同步複雜
各有優勢
記憶體、cpu
占用記憶體多,切換複雜,cpu利用率低
占用記憶體少,切換簡單,cpu利用率高
執行緒佔優
建立銷毀、切換
建立銷毀、切換複雜,速度慢
建立銷毀、切換簡單,速度快
執行緒佔優
程式設計除錯
程式設計簡單,除錯簡單
程式設計複雜,除錯複雜
程序佔優
可靠性程序間不會相互影響
乙個執行緒掛掉將導致整個程序掛掉
程序佔優
分布式適應於多核、多機分布 ;如果一台機器不夠,擴充套件到多台機器比較簡單
適應於多核分布
執行緒佔優
維度多程序
多執行緒總結
資料共享、同步
資料是分開的:共享複雜,需要用ipc;同步簡單
多執行緒共享程序資料:共享簡單;同步複雜
各有優勢
記憶體、cpu
占用記憶體多,切換複雜,cpu利用率低
占用記憶體少,切換簡單,cpu利用率高
執行緒佔優
建立銷毀、切換
建立銷毀、切換複雜,速度慢
建立銷毀、切換簡單,速度快
執行緒佔優
程式設計除錯
程式設計簡單,除錯簡單
程式設計複雜,除錯複雜
程序佔優
可靠性程序間不會相互影響
乙個執行緒掛掉將導致整個程序掛掉
程序佔優
分布式
適應於多核、多機分布 ;如果一台機器不夠,擴充套件到多台機器比較簡單
適應於多核分布
程序佔優
然後我們來看下執行緒和程序間的比較
子程序繼承父程序的屬性:
子執行緒繼承主線程的屬性:
實際使用者id,實際組id,有效使用者id,有效組id;
附加組id;
程序組id;
會話id;
控制終端;
設定使用者id標誌和設定組id標誌;
當前工作目錄;
根目錄;
檔案模式建立遮蔽字(umask);
訊號遮蔽和安排;
針對任一開啟檔案描述符的在執行時關閉(close-on-exec)標誌;
環境;連線的共享儲存段;
儲存對映;
資源限制;
程序中的所有資訊對該程序的所有執行緒都是共享的;
可執行的程式文字;
程式的全域性記憶體;
堆記憶體;
棧;檔案描述符;
訊號的處理是程序中所有執行緒共享的(注意:如果訊號的預設處理是終止該程序那麼即是把訊號傳給某個執行緒也一樣會將程序殺掉);
父子程序之間的區別:
子執行緒特有的:
fork的返回值(=0子程序);
程序id不同;
兩個程序具有不同的父程序id;
子程序的tms_utime,tms_stime,tms_cutime以及tms_ustime均被設定為0;
不繼承父程序設定的檔案鎖;
子程序的未處理鬧鐘被清除;
子程序的未處理訊號集設定為空集;
執行緒id;
一組暫存器值;
棧;排程優先順序和策略;
訊號遮蔽字;
errno變數;
執行緒私有資料;
1)需要頻繁建立銷毀的優先用執行緒。
例項:web伺服器。來乙個建立乙個執行緒,斷了就銷毀執行緒。要是用程序,建立和銷毀的代價是很難承受的。
2)需要進行大量計算的優先使用執行緒。
所謂大量計算,當然就是要消耗很多cpu,切換頻繁了,這種情況先執行緒是最合適的。
例項:影象處理、演算法處理
3)強相關的處理用執行緒,弱相關的處理用程序。
什麼叫強相關、弱相關?理論上很難定義,給個簡單的例子就明白了。
一般的server需要完成如下任務:訊息收發和訊息處理。訊息收發和訊息處理就是弱相關的任務,而訊息處理裡面可能又分為訊息解碼、業務處理,這兩個任務相對來說相關性就要強多了。因此訊息收發和訊息處理可以分程序設計,訊息解碼和業務處理可以分執行緒設計。
4)可能擴充套件到多機分布的用程序,多核分布的用執行緒。
5)都滿足需求的情況下,用你最熟悉、最拿手的方式。
至於」資料共享、同步「、「程式設計、除錯」、「可靠性」這幾個維度的所謂的「複雜、簡單」應該怎麼取捨,只能說:沒有明確的選擇方法。一般有乙個選擇原則:如果多程序和多執行緒都能夠滿足要求,那麼選擇你最熟悉、最拿手的那個。
(2)多執行緒知識點
執行緒同步方式:互斥鎖、條件變數、訊號量,讀寫鎖
1>互斥鎖:乙個時間內只准乙個執行緒進入關鍵**
pthread_mutex_init();
pthread_mutex_lock()
pthread_mutex_trylock()
pthread_mutex_unlock();
pthread_mutex_destory()(此時鎖必須為unlock狀態)
2>條件變數:利用執行緒之間共享乙個全域性變數是實現同步;基本操作有:觸發條件(當條件為true時),等待條件,掛起執行緒直到其他執行緒觸發條件
pthread_cond_init()
pthread_cond_wait()
pthread_cond_timewait() //計時等待
無論哪種等待都要配合乙個鎖使用,防止多執行緒同時請求競爭條件
pthread_cond_singal() //啟用乙個執行緒
pthread_cond_broadcast()//啟用所有執行緒
pthread_cond_destory() //沒有執行緒在等待時銷毀,否則返回ebusy
一般用法:
pthread_mutex_lock();
pthread_cond_wait();
pthread_mutex_unlock
猜測pthread_cond_wait原始碼:
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex)
......
}3> 訊號量:跟程序的訊號量一樣
標頭檔案sem_init(sem_t *sem,int pshared,int value) ; // pshared=0(linux下只能為0),為程序區域性訊號量
sem_post(sem_t *sem) //訊號量加1 v操作
sem_wait(sem_t *sem) //訊號量減1 p操作
sem_destroy(sem_t *sem)
4>讀寫鎖:多個讀鎖可以共享乙個臨界區,寫鎖與寫鎖互斥,寫鎖與讀鎖互斥
pthread_rwlock_init()
pthread_rwlock_rdlock()
pthread_rwlock_wrlock()
pthread_rwlock_unlock()
pthread_rwlock_tryrdlock()
pthread_rwlock_trywrlock()
pthread_rwlock_timerdlock()
pthread_rwlock_timewrlock()
pthread_rwlock_destroy()
擴充套件:自旋鎖
(1)請求鎖,未請求到,就一直忙等待,直到請求到這個鎖,不進行上下文切換
(2)有可能造成死鎖:遞迴呼叫,臨界區引起阻塞
(3)使用場景:鎖持有時間較短的
(4)自旋鎖與linux核心程序排程的關係
自旋鎖保護的臨界區工作在非搶占式的狀態,即使獲取不到鎖,「自旋」狀態也是禁止搶占的,在spin_unlock時重新開啟搶占
總結:1>單cpu非搶占式:自旋鎖編譯時被忽略(因為不會發生程序切換,只有乙個程序或執行緒處於臨界區,自旋鎖沒有用)
2>單cpu搶占式式:自旋鎖僅僅當做乙個設定搶占的開關(因為單cpu下不會涉及到併發訪問,設定禁止搶占就可以保證臨界區被唯一擁有)
3>多cpu:防止多程序併發訪問,防止核心搶占造成競爭
執行緒安全:原子操作、鎖、可重入、防止過度優化
原子操作:保證指令原子的指向不被打斷,linux系統提供了一些常用操作的原子指令,,包括原子整數操作和原子位操作,必須為atuomic_t型別的整數(32位的整數,24位資料,8bits的鎖)
鎖:對臨界區**進行互斥訪問
可重入:也就是可以被打斷,再次進入時沒有什麼影響,這意味著它除了使用自己棧上的變數以外不依賴於任何環境(包括static)
防止過度優化:我們可以使用volatile關鍵字試圖阻止過度優化,它可以做兩件事:第一,阻止編譯器為了提高速度將乙個變數快取到暫存器而不寫回;第二,阻止編譯器調整操作volatile變數的指令順序。
無鎖化程式設計:
針對計數器,可以使用原子加
只有乙個生產者和乙個消費者,那麼就可以做到免鎖訪問環形緩衝區(ring buffer)
rcu(read-copy-update):新舊副本切換機制,對於舊副本可以採取延遲釋放的做法。原理:對於被rcu保護的共享資料結構,讀者不需要獲取任何鎖就可以訪問他,但是寫著在訪問它時首先拷貝乙個副本,然後對副本進行修改,最後使用乙個**(callback)機制在適當的時機把指向原來資料的指標重新指向新的被修改的資料。這個時機就是所有引用該資料的cpu都退出共享資料結構的操作。寫者在訪問共享資料結構時不需要跟讀者競爭任何鎖,只有在多個寫者的情況下才要求同步。rcu技術的核心就是寫操作分為寫和更新兩步
cas(compare-and-swap):
bool cas(t* addr, t expected, t newvalue) else return false; }
(3)多程序知識點
多程序通訊:管道,命名管道,訊息佇列,共享記憶體、套接字
多程序與多執行緒的區別
據說這個問題很重要,要從多個方面總結。多執行緒和多程序的區別 小結 多執行緒還是多程序的選擇及區別 關於程序和執行緒對於全域性變數共享的問題學習總結 程序是資源分配的最小單位,執行緒是cpu排程的最小單位。同一程序的不同執行緒會共享程序記憶體空間中的全域性區和堆。執行緒私有的是棧和暫存器。因此。區域...
多程序與多執行緒的區別
多程序與多執行緒的區別?解 1 從資料共享 同步方面來講,多程序資料共享複雜,需要用ipc,資料是分開的,同步簡單 多執行緒資料共享簡單,但也是因為這個原因導致同步複雜。2 從內 存 cpu 方面來講,多程序占用記憶體多,切換複雜,cpu利用率低 多執行緒占用記憶體少,切換簡單,cpu利用率高。3 ...
Java多程序與多執行緒的區別
作業系統中的多工 在同一時刻執行多個程式的能力。作業系統將cpu的時間片分配給每乙個程序,給人並行處理的感覺。多執行緒程式在較低的層次上擴充套件了多工的概念 乙個程式同時執行多個任務。通常,每乙個任務稱為乙個執行緒。可以同時執行乙個以上執行緒的程式稱為是多執行緒程式。多程序與多執行緒的區別 本質的區...