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


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

  我們認為首先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操作上。

2.同步不阻塞:在B階段依然采用輪詢的方式直至獲得完成標志,但是此輪詢不同於上面的輪詢過程,而是在相鄰的輪詢中完成了上下文切換去處理別的任務的,所以是同步不阻塞

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM