說非同步前,首先講講這些概念,非同步/同步、多線程。 非同步:是指呼叫另一操作後,不等待其結果,繼續執行之後的操作,若之後沒有其他操作,當前線程將進入睡眠狀態,而CPU時間將有機會切至其他線程。在非同步操作完成後通過回調函數的方式獲取通知與結果。非同步的實現方式有多種,如多線程與完成埠。多線程將非同步操作放...
概念
說非同步前,首先講講這些概念,非同步/同步、多線程。
非同步:是指呼叫另一操作後,不等待其結果,繼續執行之後的操作,若之後沒有其他操作,當前線程將進入睡眠狀態,而CPU時間將有機會切至其他線程。在非同步操作完成後通過回調函數的方式獲取通知與結果。非同步的實現方式有多種,如多線程與完成埠。多線程將非同步操作放入另一線程中運行,通過輪詢或回調方法得到完成通知;完成埠,由操作系統接管非同步操作的調度,通過硬體中斷,在完成時觸發回調方法,此方式不需要占用額外線程。
同步:與非同步相對應。
多線程:一般指同一進程中多個線程(包含其數據結構、上下文與代碼片段)協作運行。在多核電腦中多個線程將有機會同時運行於多個核上,如果線程中進行的是計算,則行成並行計算。
.NET中的非同步
多線程
概念中提到的用多線程方式實現非同步操作,可以使用各種多線程的介面。參照後文中.NET中的多線程。
Classic Async Pattern(CAP) (BeginXXX & EndXXX)
委托(delegate),文件讀寫(FileStream)等等許多的類裡面都包含了BeginXXX & EndXXX的非同步介面,利用這些介面即可以實現非同步編程。但是這個模型裡面到底是使用多線程還是完成埠卻取決於具體的實現,委托的(BeginInvoke & EndInvoke)是基於多線程實現。而FileStream要使用完成埠也要傳入FileOptions.Asynchronous提前告訴你將要使用非同步IO讀取,否則將會使用預設的多線程實現。
Event-based Async Pattern(EAP)(XXXAsync & XXXComplete)
.NET Framework除了提供上面這種編程模式外,還提供了基於事件的非同步編程模式。比如WebClient的很多方法就提供了非同步版本,比如DownloadString方法。
同步版本:
public string DownloadString(string url);
非同步版本:
public void DownloadStringAsync(string url);
public event DownloadStringCompleteEventHandler DownloadStringComplete;
Task-based Asynchronous Pattern(TAP)(async & await)
以上兩種非同步編程模型(CAP & EAP)都將非同步實現分成了兩部分:一部分發起非同步操作,另一部分獲得結果。如果多個非同步需要順序執行的時候,那麼就會造成一個非同步回調里嵌套另一個非同步調用,代碼變得非常混亂。
而TAP就是為瞭解決這個回調災難的。而且還引入了兩個新的語言關鍵字用於方便用戶編寫非同步編程代碼(async & await)。
.NET中的多線程
Thread
托管線程的基礎類。
ThreadPool
內部實現的線程池,迴圈使用線程,避免線程頻繁的創建,提高效率。
Task
使用內部實現的線程池。更方便的線程創建,異常捕獲,多任務同步。
線程鎖
獨占鎖
Monitor & lock
互斥鎖
Mutex 可以實現跨進程的鎖。
讀寫鎖
ReaderWriterLock,讀寫(Reader-Writer)兩種請求,按照請求到達的順序,一共有四種:
Reader-Reader,第二個不需等待,直接獲得讀控制權;
Reader-Writer,第二個需要等待第一個調用ReleaseReaderLock()釋放讀控制權後,才能獲得寫控制權;
Writer-Writer,第二個需要等待第一個調用ReleaseWriterLock()釋放寫控制權後,才能獲得寫控制權;
Writer-Reader,第二個需要等待第一個調用ReleaseWriterLock()釋放寫控制權後,才能獲得讀控制權。