<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
說起Golang(後面統稱為Go),就想到他的高並行特性,在深入一些就是 Goroutine。在大家被它優雅的語法和簡潔的程式碼實現的高並行程式所折服時,其實C#/.NET也可以很容易的做到。今天我們來參照Go,來用C#實現它所採用的的CSP並行模型。
這東西我一開始以為很簡單,後面差了資料發現它獨樹一幟,自己是一門語言,也是一套理論。這邊我不深入的對它做過多的見解,我怕耽誤大家=_=,大家可以看看wiki。
wiki:https://en.wikipedia.org/wiki/Communicating_sequential_processes
我們從Go的角度對它進行一些分析,摘抄一段概要:
“用於描述兩個獨立的並行實體通過共用的通訊 channel(管道)進行通訊的並行模型。 CSP中channel是第一類物件,它不關注傳送訊息的實體,而關注與傳送訊息時使用的channel。”
好了,單獨寫出 CSP 是為了讓大家瞭解這是一套獨立於語言的東西,大家有興趣可以檢視wiki和搜尋一些其它資料。
Channel(通道)
Goroutine(不知道怎麼翻譯,大家可以理解成一個“工作者”,不是工作者執行緒。本質是實現了協程。)
大家都很明白執行緒能做什麼,但協程是個什麼東西?比起執行緒又如何呢?
我們重新思考一些東西。
CPU:核心、超執行緒
OS:執行緒
程式語言:執行緒池
這邊不做細講,只是大概點到一下。
我們所做的任何計算都要經由CPU計算,而CPU的核數直接決定了我們能給CPU執行幾件事情。
我們現在所常用的OS內部都有一個輪詢,用時間片的形式來分配任何輪流使用CPU執行計算,執行緒就是這些任務的載體。
這塊的概念非常龐大(還有牽扯到,什麼是並行,什麼事並行),本文的重點不是這些,大家有興趣後面可以單獨開一篇文章來解釋這塊的內容。
迴歸本文,現在我們知道執行緒是作業系統級別用來共用CPU的一種技術實現,多執行緒程式設計早在各大語言遍地開花,被用的惟妙惟肖,百花齊放。
那麼為什麼需要協程呢?
這塊又是一個大知識點,這邊也不多做介紹。
大家只要明白,執行緒並不是廉價的,一個執行緒的創立有至少兩點的開銷
執行緒是可以持有邏輯資料的(比如,HttpContext.Current,等物件)所以必定是佔用記憶體的(至於佔用了多少記憶體不同的語言和OS不一樣)
如果一個CPU是4核的,同時就只能處理4件任務,一個OS的執行緒越多他們輪訓一整圈所耗的時間就更長。而每次排程執行緒時都需要複製當前執行緒上下文的狀態,再去讀取準備排程執行緒上下文的狀態。
這邊可以看到最後一點,有時候多執行緒反而會比單執行緒更加的慢,所以多執行緒提升效能本質上其實是假的。多執行緒並不會提升程式效能。
我知道這邊肯定有人會心存疑問,絕大數的人都說用多執行緒來提升效能,為什麼這邊說多執行緒會比單執行緒慢?
我們這邊想一下:PHP 和 NodeJS,PHP預設不支援多執行緒,NodeJS採用單執行緒事件輪詢,他們的效率比擁有多執行緒的語言低嗎?並不會。
多執行緒之所以快是因為作弊,別人一個人乾的事情你叫兩個人去幹當然會比單執行緒快。這也有非常大的限制,多執行緒所執行的東西儘可能避免共用,不然你的效率還是可能不如單執行緒。
這邊說的有點跑題,這塊的內容實在太大,大家只要知道,執行緒即使不昂貴也絕不廉價。
針對這個問題,各大語言都推出了一個叫做執行緒池的技術,我申請一批執行緒,持有他,等到有任務的時候直接使用,這樣我就不會頻繁的建立和銷燬執行緒了。這樣大大提升了效率。
在.NET中,很早就提倡任何需要執行緒的時刻都使用 ThreadPool。
ps:現在覺大多數(我還沒見過)的語言(runtime)中,執行緒與作業系統的執行緒是一一對應的。
協程與執行緒是多對一的關係,有多個協程會對應到一根執行緒上。跟執行緒和CPU是一樣的關係。
執行緒是為了共用CPU,而協程是為了共用執行緒。
協程是應用層面的自有“執行緒”實現。也就是說在不改變OS的執行緒邏輯下,自己構建了一套 “執行緒”系統。
為什麼不直接改動OS的執行緒,讓其更輕?我個人覺得 1是歷史相容性問題,2是必要性問題,執行緒是一個很好的抽象邏輯。實現協程完全可以通過執行緒來完成。
我們來思考一個場景
抓取百度、google、bing的html。
多執行緒的做法是
啟動三個執行緒,分別對百度、google、bing發起HTTP GET請求。這時候使用了三個執行緒。
協程的做法是(極端)
啟動一個執行緒對百度發起HTTP GET請求,將任務放入佇列,在對google發起HTTP GET請求,將任務放入佇列,在對bingHTTP GET請求將任務放入佇列。
這時候只需要使用一個執行緒(極端情況下,其實大多數實現來說至少需要兩個執行緒,因為需要有一個後臺執行緒去監聽任務佇列,當任務完成後再分配一個可用執行緒去處理下面的邏輯)
為什麼說極端情況下?因為協程有時候也可能會與執行緒一一對應,比如你的CPU有8個核心,同時跑4個協程也有可能會分配4根執行緒單獨去處理這4個任務,這主要取決於排程演演算法。
總結:協程是為了提升執行緒利用率,減少執行緒的無用功(大多數是IO堵塞),協程也更適合IO密集型的場景。
可以看到,3個任務是非同步執行的,但都由執行緒4來處理,也就是說三個非同步任務只用了一根執行緒。
講了這麼大篇幅的協程,終於迴歸了今天的主題。
其實單單實現CSP來說根本不用理清執行緒和協程。但今天主要對比的是Go中的CSP,所以如果沒有協程基本是沒有意義的。
C#如何對應,CSP中最重要的Channel呢?
答案就是:BlockingCollection<T>
我們來看一個例子
抓取一批網站並輸出網站的title
發起 HTTP GET 請求 和分析Title的程式碼邏輯如下:
主程式的程式碼如下:
執行邏輯
執行結果如下:
去除實現上的一些邏輯,本質上沒太多區別。
但Go有一個天生優勢就是它是新時代的語言,拋棄了執行緒。也就是說Go層面沒有執行緒的東西,它只有協程。
但.NET中執行緒已經擁有了好多年,大量的類庫、驅動使用執行緒來完成。
所以你在上一層就算使用了協程,執行到底部不一定只有一根執行緒來完成,底部可以自己建立執行緒來執行邏輯,今天篇幅關係不做過多說明。後面我們在介紹這塊的內容。
最後總結一個要點,多執行緒、協程並不能提升效能,它們所達到的目的只是提高CPU利用率。
今天本來想詳細寫BlockingCollection<T>的使用說明,但協程等概念佔了大量的篇幅,後面我們再來詳細介紹.NET中的非同步程式設計。
以上就是C#代替go採用的CSP並行模型實現的詳細內容,更多關於C#實現go採用CSP並行模型的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45