我爲何喜歡用C#來作併發編程

(此文章同時發表在本人微信公衆號「dotNET每日精華文章」,歡迎右邊二維碼來關注。)html

題記:就語言和運行時層面,C#作併發編程一點都不弱,缺的是生態和社區。git

硅谷才女朱贇(個人家門)昨天發了一篇文章《爲何用 Java —— 關於併發編程》,讓你們學習了Java中如何進行併發編程的一些基本知識。做爲一個將近15年的.NET程序員,我以爲有必要給你們補充介紹一下C#進行併發編程的知識(固然不會太深刻講解)。這篇文章無心進行技術比較,畢竟技術只是工具(大同小異,各有千秋),主要仍是看用工具的人。程序員

併發(英文Concurrency),實際上是一個很泛的概念,字面意思就是「同時作多件事」,不過方式有所不一樣。在.NET的世界裏面,併發通常涉及以下幾個方面:github

  1. 多線程編程(已過期,不介紹)
  2. 異步編程
  3. 並行編程
  4. 響應式編程
  5. 數據流編程

爲了支持以上編程,.NET提供了不少基礎功能,好比:委託,匿名函數,Lambda表達式,線程池,Task模型,支持併發的集合(線程安全集合和不可變集合) ,調度器,同步功能。在這裏,就不對這些內容進行介紹了,你們能夠自行搜索學習。另外,對於Actor模型,.NET中也有支持,但我不認爲它屬於語言/運行時層面的併發,它更像架構層面的併發,我最後會簡單介紹。編程

1,異步編程

異步編程就是使用future模式(又稱promise)或者回調機制來實現(Non-blocking on waiting)。promise

若是使用回調或事件來實現(容易callback hell),不只編寫這樣的代碼不直觀,很快就容易把代碼搞得一團糟。不過在.NET 4.5(C# 5)中引入的async/await關鍵字(在.NET 4.0中經過添加Microsoft.Bcl.Async包也可使用),讓編寫異步代碼變得容易和優雅。經過使用async/await關鍵字,能夠像寫同步代碼那樣編寫異步代碼,全部的回調和事件處理都交給編譯器和運行時幫你處理了。安全

使用異步編程有兩個好處:不阻塞主線程(好比UI線程),提升服務端應用的吞吐量。因此微軟推薦ASP.NET中默認使用異步來處理請求。服務器

要詳細瞭解異步編程,能夠參考官方文檔:https://msdn.microsoft.com/en-us/library/jj152938(v=vs.110).aspx和《Async in C# 5.0》這本書。另外,在這個官方文檔中,微軟還特地把異步編程分做了3種不一樣的模型:基於任務的模式(TAP)就是我上面推薦的這種,基於事件的模式(EAP)和異步編程模型(APM)我上面不推薦的事件和回調。微信

2,並行編程

並行編程的出現其實是隨着CPU有多核而興起的,目的是充分利用多核CPU的計算能力。並行編程因爲會提升CPU的利用率,更適合客戶端的一些應用,對於服務端的應用可能會形成負面影響(由於服務器自己就具備並行處理的特色,好比IIS會並行的處理多個請求)。我本身使用並行編程最多的場景是以前分析環境數據不肯定度的時候,使用並行的方式計算蒙特卡洛模擬(計算上千次以後擬合),固然後來我使用泰勒級數展開來計算不肯定度,沒有這麼多的計算量就無需並行了。固然在計算多方案結果比較的狀況下,仍是繼續使用了併發計算。多線程

在.NET中,並行的支持主要靠.NET 4.0引入的任務並行庫和並行LINQ。經過這些庫能夠實現數據並行處理(處理方式相同,輸入數據不一樣,好比我上面提到的應用場景)或者任務並行處理(處理方式不一樣,且數據隔離)。經過使用並行處理庫,你不用關心Task的建立和管理(固然更不用說底層的線程了),只須要關注處理任務自己就好了。

具體的用法仍是參考官方文檔:https://msdn.microsoft.com/en-us/library/dd460693(v=vs.110).aspx,固然《Parallel Programming with Microsoft .NET》這本書也行。

3,響應式編程

響應式編程最近成爲了一個Buzzword,其實微軟6年前就開始給.NET提供一個Reactive Extensions了。一開始要理解響應式編程有點困難,可是一旦理解了,你就會對它的強大功能愛不釋手。簡單來講,響應式編程把事件流看做數據流,不過數據流是從IEnumable中拉取的,而事件流是從IObservable推送給你的。爲何響應式編程能夠實現併發呢?這是由於Rx作到線程不可知,每次事件觸發,後續的處理會從線程池中任意取出一個線程來處理。且能夠對事件設置窗口期和限流。舉個例子,你能夠用Rx來讓搜索文本框進行延遲處理(而不用相似我很早的時候用個定時器來延遲了)。

要詳細瞭解Rx最好的方式就是瀏覽 IntroToRx.com 這個網站,固然還有官方文檔:https://msdn.microsoft.com/en-us/data/gg577609

4,數據流編程

數據流(DataFlow)編程可能你們就更陌生了,不過仍是有些經常使用場景可使用數據流來解決。數據流實際上是在任務並行庫(TPL)上衍生出來的一套處理數據的擴展(也結合了異步的特性),TPL也是處理並行編程中任務並行和數據並行的基礎庫。

望文生義,TPL DataFlow就是對數據進行一連串處理,首先爲這樣的處理定義一套網格(mesh),網格中能夠定義分叉(fork)、鏈接(join)、循環(loop)。數據流入這樣的處理網格就可以並行的被處理。你能夠認爲網格是一種升級版的管道,實際上不少時候就是被看成管道來使用。使用場景能夠是「分析文本文件中詞頻」,也能夠是「處理生產者/消費者問題」。

參考資料固然也是官方文檔:https://msdn.microsoft.com/en-us/library/hh228603(v=vs.110).aspx

5,Actor模型

Scala有Akka,其實微軟研究院也推出了Orleans來支持了Actor模型的實現,固然也有Akka.NET可用。Orleans設計的目標是爲了方便程序員開發須要大規模擴展的雲服務, 可用於實現DDD+EventSourcing/CQRS系統。

官方網站是:http://dotnet.github.io/orleans/,善友也有介紹:http://www.cnblogs.com/shanyou/p/4295523.html

那麼,我爲何喜歡使用C#來作併發編程呢?顯而易見,有上面這些唾手可得的工具,使用C#一樣能夠輕易開發併發程序。

相關文章
相關標籤/搜索