同步,異步,阻塞,非阻塞以及幾種常見的服務器模型

  在多數的狀況下,咱們談論這幾個概念時都是涉及到I/O操做時,當計算機在等待數據從磁盤或者其餘存儲設備(網絡socket)到達用戶進程所用空間時所涉及的幾個概念。python

  咱們認爲首先CPU會發出一個I/O操做的通知,而後文件系統或其餘會調用相關設備執行這些操做,最後當數據到達用戶空間後發出一箇中斷的完成標誌,因而在這個從CPU發出調用到收到完成標誌的過程當中就存在一個時間差。如今就有了兩個重要的概念:完成標誌時間差同步與異步是針對獲取完成標誌而言的,而阻塞與非阻塞是針對時間差而言的。服務器

 

  同步異步:獲取完成標誌的方式。若是是採用輪詢的方式監測I/O操做是否完成稱爲同步,而以經過回調通知的方式得到完成標誌則稱爲異步。網絡

  阻塞非阻塞:在那段時間差的過程當中,CPU有沒有處理別的事情,若是處理過別的事情則是非阻塞,若是並無處理過別的事情則是阻塞。多線程

 *1,2表明輪詢I/O操做的進行狀態,3表明I/O操做已經完成併發

咱們把一個I/O調用看作上面A和B兩個過程,A階段是CPU發出I/O調用【此階段是十分快速的】,B階段是相關設備把數據從目標位置轉移到用戶空間的過程【此階段就會因爲數據量以及數據所在設備的遠近而所用時間大爲不一樣】,容易明白的是上面四個概念都是針對B階段在數據遷移過程當中此進程/線程所對應的CPU狀態而言的,因此用這個過程來看看上面四個概念的組合:異步

1.同步阻塞:便是在B階段CPU一直採用輪詢的方式直到得到完成標誌,因此此段時間CPU一直阻塞在此I/O操做上。socket

2.同步不阻塞:在B階段依然採用輪詢的方式直至得到完成標誌,可是此輪詢不一樣於上面的輪詢過程,而是在相鄰的輪詢中完成了上下文切換去處理別的任務的,因此是同步不阻塞高併發

3.異步阻塞:也就是所沒有上面的1,2過程,當I/O操做完成後回調通知CPU已完成【便是3過程】,可是此階段CPU處於休眠狀態而不處理別的任務。spa

4.異步不阻塞:和上面同樣沒有1,2過程而是經過回調知道I/O操做已完成,可是並無休眠,而是在此階段處理其餘任務。線程

綜上所述:異步不阻塞是最高效的。

 

在實際中常採用多線程模擬理想異步非阻塞模式:一個主線程用於計算,多個線程用於執行I/O操做【多是上面四種的任意形式】

  

幾種常見服務器模型:

  1.同步式:一次處理一個請求,其他請求處於等待狀態

  2.每請求/每進程: 爲每一個請求啓動一個進程【不具有擴展功能,系統志願有限】

  3.每請求/每線程:爲每一個請求啓動一個線程【每一個線程佔必定內存,故受限於內存,還會拖慢服務器】【Apache就是採用的這種方式】

  4.事件驅動:Node與Nginx採用事件驅動方式而不建立新線程【省去了線程建立/刪除的系統開銷以及線程上下文切換,因此可以處理更多的鏈接】【python的Twisted,Ruby的Event Machine以及Perl的AyEvent也是事件驅動,可是他們並非很成功】

 

須要注意的是對於高併發【註釋1】的程序每每採用「同步非阻塞」而不是「多線程的同步阻塞」,在合理設計任務調度的不一樣階段可以使得併發數遠大於並行數,須要注意的是在高併發情況下爲每一個任務建立一個線程的開銷很大,因此並不採用多線程的同步阻塞。

註釋1:併發:同時進行的任務數量

     並行:可同時工做的物理資源(CPU核數等等)

 

另外,有個概念是異步IO,其主要是說在同一線程中當遭遇IO時,並不等待而是執行下面的操做直到IO操做完成後再切回當前,其實就是同步非阻塞

  http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143208573480558080fa77514407cb23834c78c6c7309000

 

參考:

1:http://blog.jobbole.com/99765/

2:深刻淺出Node.js

相關文章
相關標籤/搜索