c語言多線程詳解?
概念
線程:線程是程序中的壹個執行流,每個線程都有自己的專有寄存器(棧指針、程序計數器等),但代碼區是***享的,即不同的線程可以執行同樣的函數。
多線程:多線程是指程序中包含多個執行流,即在壹個程序中可以同時運行多個不同的線程來執行不同的任務,也就是說允許單個程序創建多個並行執行的線程來完成各自的任務。
C語言的開始設計,並未設計多線程的機制,由於隨著軟硬件的發展及需求的發展。後來C語言才開發了線程庫以支持多線程的操作、應用。
主要基於Linux介紹C多線程。在編譯C的多線程時候,壹方面必須指定LinuxC語言線程庫多線程庫pthread,才可以正確編譯(例如:gcctest.c-otest-lpthread);另壹方面要包含有關線程頭文件#includepthread.h>。
linux怎麽查看壹個進程的所有線程?
使用ps命令
常用參數:
-a顯示所有進程(等價於-e)(utility)
-a顯示壹個終端的所有進程,除了會話引線
-n忽略選擇。
-d顯示所有進程,但省略所有的會話引線(utility)
-x顯示沒有控制終端的進程,同時顯示各個命令的具體路徑。dx不可合用。(utility)
-ppid進程使用cpu的時間
-uuidorusername選擇有效的用戶id或者是用戶名
-ggidorgroupname顯示組的所有進程。
uusername顯示該用戶下的所有進程,且顯示各個命令的詳細路徑。如:psuzhang;(utility)
-f全部列出,通常和其他選項聯用。如:ps-faorps-fxandsoon.
-l長格式(有f,wchan,c等字段)
-j作業格式
-o用戶自定義格式。
v以虛擬存儲器格式顯示
s以信號格式顯示
-m顯示所有的線程
-h顯示進程的層次(和其它的命令合用,如:ps-ha)(utility)
e命令之後顯示環境(如:ps-de;ps-ae)(utility)
h不顯示第壹行
ps命令常用用法:
1)psa顯示現行終端機下的所有程序,包括其他用戶的程序。
2)ps-a顯示所有進程。
3)psc列出程序時,顯示每個程序真正的指令名稱,而不包含路徑,參數或常駐服務的標示。
4)ps-e此參數的效果和指定"a"參數相同。
5)pse列出程序時,顯示每個程序所使用的環境變量。
6)psf用ascii字符顯示樹狀結構,表達程序間的相互關系。
7)ps-h顯示樹狀結構,表示程序間的相互關系。
8)ps-n顯示所有的程序,除了執行ps指令終端機下的程序之外。
9)pss采用程序信號的格式顯示程序狀況。
10)pss列出程序時,包括已中斷的子程序資料。
11)ps-t指定終端機編號,並列出屬於該終端機的程序的狀況。
12)psu以用戶為主的格式來顯示程序狀況。
13)psx顯示所有程序,不以終端機來區分。
最常用的方法是ps-aux或ps-ef,然後再利用壹個管道符號導向到grep去查找特定的進程,然後再對特定的進程進行操作。
Linux多線程通信?
PIPE和FIFO用來實現進程間相互發送非常短小的、頻率很高的消息;
這兩種方式通常適用於兩個進程間的通信。
***享內存用來實現進程間***享的、非常龐大的、讀寫操作頻率很高的數據(配合信號量使用);這種方式通常適用於多進程間通信。
其他考慮用socket。這裏的“其他情況”,其實是今天主要會碰到的情況:分布式開發。
在多進程、多線程、多模塊所構成的今天最常見的分布式系統開發中,socket是第壹選擇
。消息隊列,現在建議不要使用了----因為找不到使用它們的理由。在實際中,我個人感覺,PIPE和FIFO可以偶爾使用下,***享內存都用的不多了。在效率上說,socket有包裝數據和解包數據的過程,所以理論上來說socket是沒有PIPE/FIFO快,不過現在計算機上真心不計較這麽壹點點速度損失的。妳費勁糾結半天,不如我把socket設計好了,多插壹塊CPU來得更劃算。另外,進程間通信的數據壹般來說我們都會存入數據庫的,這樣萬壹某個進程突然死掉或者整個服務器死了,也不至於丟失重要數據、便於回滾到之前的狀態。從這個角度考慮,適用***享內存的情況也更少了,所以socket使用得更多。再多說壹點關於***享內存的:***享內存的效率確實高,但它的重點在“***享”二字上。如果的確有好些進程***享壹大塊數據(如果把每個進程都看做是類的對象的話,那麽***享數據就是這個類的static數據成員),那麽***享內存就是壹個不二的選擇了。但是在面向對象的今天,我們更多的時候是多線程+鎖+線程間***享數據。因此***享進程在今天使用的也越來越少了。不過,在面對壹些極度追求效率的需求時,***享內存就會成為唯壹的選擇,比如高頻交易系統。除此以外,壹般是不需要特意使用***享內存的。另外,PIPE和***享內存是不能跨LAN的
(FIFO可以但FIFO只能用於兩個進程通信)如果妳的分布式系統隨著需求的增加而越來越大所以妳想把不同的模塊放在不同機器上而妳之前開發的時候用了PIPE或者***享內存,那麽妳將不得不對代碼進行大幅修改......同時,即使FIFO可以跨越LAN,其代碼的可讀性、易操作性和可移植性、適應性也遠沒有socket大。這也就是為什麽壹開始說socket是第壹選擇的原因。最後還有個信號簡單說壹下。請註意,是信號,不是信號量。
信號量是用於同步線程間的對象的使用的(建議題主看我的答案,自認為比較通俗易懂:semaphore和mutex的區別?-Linux-知乎
)。信號也是進程間通信的壹種方式。比如在Linux系統下,壹個進程正在執行時,妳用鍵盤按Ctrl+c,就是給這個進程發送了壹個信號。進程在捕捉到這個信號後會做相應的動作。雖然信號是可以自定義的,但這並不能改變信號的局限性:不能跨LAN、信息量極其有限
。在現代的分布式系統中,通常都是消息驅動:
即進程受到某個消息後,通過對消息的內容的分析然後做相應的動作。如果妳把妳的分布式系統設置成信號驅動的,這就表示妳收到壹個信號就要做壹個動作而壹個信號的本質其實就是壹個數字而已。這樣系統稍微大壹點的話,系統將變得異常難以維護;甚至在很多時候,信號驅動是無法滿足我們的需求的。因此現在我們壹般也不用信號了。因此,請記住:除非妳有非常有說服力的理由,否則請用socket。
順便給妳推薦個基於socket的輕量級的消息庫:ZeroMQ。linux多線程詳解?
1.進程是操作系統分配資源的基本單位。而線程通俗來講就是壹個進程中壹個執行流。
2.這裏以串行與並行下載文件舉例,如果我們使用串行的方式去下載多個文件,那麽得到的結果是,將這些文件逐個按個的下載,即上壹個下載完成之後才會下載接下來的文件。
3.如果使用並行的方式下載,那麽這些文件就會壹次同時下載多個文件,而不是等待上壹個下載完後才繼續下載接下來的,大大的提高了下載效率。
cpu多線程和jvm多線程?
壹cpu個數、核數、線程數的關系
cpu個數:是指物理上,也及硬件上的核心數;
核數:是邏輯上的,簡單理解為邏輯上模擬出的核心數;壹個CPU核心數模擬出2線程的CPU
線程數:是同壹時刻設備能並行執行的程序個數,線程數=cpu個數*核數,及程數=cpu個數(2)*核數(2)=4
Windows:wmic然後物理CPU數“cpugetNumberOfCores”,CPU核心數“cpugetNumberOfLogicalProcessors”
Linux:
查看CPU個數cat/proc/cpuinfo|grepphysicalid|sort|uniq|wc-l
查看核數cat/proc/cpuinfo|grepcpucores|uniq
二cpu線程數和Java多線程
(1)線程是CPU級別的,單個線程同時只能在單個cpu線程中執行
(2)Java多線程並不是由於cpu線程數為多個才稱為多線程,當Java線程數大於cpu線程數,操作系統使用時間片機制,采用線程調度算法,頻繁的進行線程切換。
(3)線程是操作系統最小的調度單位,進程是資源(比如:內存)分配的最小單位
(4)Java中的所有線程在JVM進程中,CPU調度的是進程中的線程
線程的調度是指按照特定的機制為多個線程分配CPU的使用權。有兩種調度模型:分時調度模型和搶占式調度模型
分時調度模型是指讓所有線程輪流獲得CPU的使用權,並且平均分配每個線程占用CPU的時間片。
Java虛擬機采用搶占式調度模型,是指優先讓可運行池中處於就緒態的線程中優先級高的占用CPU,如果可運行池中線程的優先級相同,那麽就隨機選擇壹個線程,使其占用CPU,處於運行狀態的線程會壹直執行,直至它不得不放棄CPU,壹個線程會因為以下原因放棄CPU:
(1)Java虛擬機讓當前線程暫時放棄CPU,轉到就緒態,使其他線程獲得運行機會
(2)當前線程因為某些原因而處於阻塞狀態
(3)線程運行結束
Java線程讓步:
3.Thread.yield()方法
就是說當壹個線程使用了這個方法之後,它就會把自己CPU執行的時間讓掉,讓自己或者其它的線程運行,註意是讓自己或者其他線程運行(根據CPU的調度),並不是單純的讓給其他線程。
4.等待其他線程結束:join()
當前運行的線程可以調用另壹個線程的join()方法,當前運行的線程將轉到阻塞狀態,直至另壹個線程運行結束,它才會恢復運行(阻塞恢復到就緒)