進程與線程

程序:程序是一個靜態的概念,是完成某個功能的指令集合

一、進程

進程是動態的,一般由程序、數據集合和進程控制塊三部分組成,程序用於描述進程要完成的功能,是控制進程執行的指令集;數據集合是程序在執行時所需要的數據和工作區;進程控制塊(PCB)包含進程的描述信息和控制信息,是進程存在的唯一標示

進程具有的特徵:

動態性:進程是程序的一次執行過程,是臨時的,有生命週期的,是動態產生的,動態消亡的

併發性:任何進程都可以同其他進程一起併發執行

獨立性:進程 是系統進行資源分配的一個獨立單位

結構性:進程由程序、數據和進程控制塊三部分組成

二、線程

線程是程序執行中的一個單一的順序控制流程,是CPU調度的最小單位,一個進程有一個或者多個線程,各個線程之間共享進程的內存空間,一個標準的線程由線程ID、當前指令指針(PC),寄存器和堆棧組成

線程的棧被自動分配到進程的內存空間中

線程和進程的區別:

(1)線程是程序執行的最小單位,而進程是操作系統分配資源的最小單位

(2)一個進程由一個或者多個線程組成,線程是一個進程中代碼的不同執行路線

(3)進程之間相互獨立,但是同一進程下的各個線程之間共享程序的內存空間(包括代碼段、數據集、堆等)及一些進程級的資源(打開文件和信號),某進程內的線程在其它進程中不可見

(4)調度和切換:線程上下文切換比進程上下文切換要快的多

Java中線程堆棧是系統某個時刻的線程運行狀態

三、Node.js的單線程

Node.js是單線程的,也就是說當多個用戶發出請求的時候,我並不會爲每個用戶去創建一個線程

單線程使得Node.js不必去頻繁的創建、切換線程,使得運行速度加快
單線程保證了絕對的線程安全,不必擔心同一變量同時被多個線程進行讀寫而造成的程序崩潰

單線程的異步和非阻塞

(1)Node.js如何做到I/O的異步和非阻塞呢?

Node.js在底層訪問I/O的時候還是多線程的,Node.js的fs模塊的源碼,裏面會用到libuv來處理I/O,所以在我們看來Node.js的代碼就是非阻塞和異步形式的

(2)阻塞/非阻塞與異步/同步是兩個不同的概念,同步不代表阻塞,但是阻塞肯定就是同步了

舉個現實生活中的例子,我去食堂打飯,我選擇了A套餐,然後工作人員幫我去配餐,如果我就站在旁邊,等待工作人員給我配餐,這種情況就稱之爲同步;若工作人員幫我配餐的同時,排在我後面的人就開始點餐,這樣整個食堂的點餐服務並沒有因爲我在等待A套餐而停止,這種情況就稱之爲非阻塞。這個例子就簡單說明了同步但非阻塞的情況。

再如果我在等待配餐的時候去買飲料,等聽到叫號再回去拿套餐,此時我的飲料也已經買好,這樣我在等待配餐的同時還執行了買飲料的任務,叫號就等於執行了回調,就是異步非阻塞了。

阻塞的單線程

既然Node.js是單線程異步非阻塞的,是不是我們就可以高枕無憂了呢?

還是拿上面那個買套餐的例子,如果我在買飲料的時候,已經叫我的號讓我去拿套餐,可是我等了好久纔拿到飲料,所以我可能在大廳叫我的餐號之後很久纔拿到A套餐,這也就是單線程的阻塞情況。

在瀏覽器中,js都是以單線程的方式運行的

由如下代碼:

var start = Date.now();//獲取當前時間戳
setTimeout(function () {
    console.log(Date.now() - start);
    for (var i = 0; i < 1000000000; i++){//執行長循環
    }
}, 1000);
setTimeout(function () {
    console.log(Date.now() - start);
}, 2000);

最終我們的打印結果是:(結果可能因爲你的機器而不同)

1000
3738

對於我們期望2秒後執行的setTimeout函數其實經過了3738毫秒之後才執行,換而言之,因爲執行了一個很長的for循環,所以我們整個Node.js主線程被阻塞了,如果在我們處理100個用戶請求中,其中第一個有需要這樣大量的計算,那麼其餘99個就都會被延遲執行。

其實雖然Node.js可以處理數以千記的併發,但是一個Node.js進程在某一時刻其實只是在處理一個請求

參考這裏:http://www.cnblogs.com/chris-oil/p/5339305.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章