C 併發程式設計 非同步程式設計與多執行緒

2022-02-14 10:04:14 字數 4507 閱讀 3142

併發:同時做多件事情

多執行緒:併發的一種形式,它採用多個執行緒來執行程式。

並行處理:把正在執行的大量的任務分割成小塊,分配給多個同時執行的執行緒。並行處理是多執行緒的一種,而多執行緒是併發的一種。

非同步程式設計:併發的一種形式,它採用 future 模式或**(callback)機制,以避免產生不必要的 執行緒,非同步程式設計的核心理念是非同步操作:啟動了的操作將會在一段時間後完成。這個操作 正在執行時,不會阻塞原來的執行緒。啟動了這個操作的執行緒,可以繼續執行其他任務。當 操作完成時,會通知它的 future,或者呼叫**函式,以便讓程式知道操作已經結束,

async 和 await:這讓非同步程式設計變得幾乎和同步(非併發)程式設計一樣容易。await的作用:啟動乙個將會被執行的task(該task將會在新執行緒中執行),並立即返回,所以await所在的函式不會被阻塞,當task完成後,繼續執行await後面的**。

通常情況下,乙個併發程式要使用多種技術。大多數程式至少使用了多執行緒(通過執行緒 池)和非同步程式設計

非同步程式設計有兩大好處。第乙個好處是對於面向終端使用者的 gui 程式:非同步程式設計提高了響應 能力。我們都遇到過在執行時會臨時鎖定介面的程式,非同步程式設計可以使程式在執行任務時 仍能響應使用者的輸入。第二個好處是對於伺服器端應用:非同步程式設計實現了可擴充套件性。服務 器應用可以利用執行緒池滿足其可擴充套件性,使用非同步程式設計後,可擴充套件性通常可以提高乙個數 量級。

現代的非同步 .net 程式使用兩個關鍵字:async 和 await。async 關鍵字加在方法宣告上, 它的主要目的是使方法內的 await 關鍵字生效(為了保持向後相容,同時引入了這兩個關 鍵字)。如果 async 方法有返回值,應返回 task;如果沒有返回值,應返回 task。這些 task 型別相當於 future,用來在非同步方法結束時通知主程式。

async 方法在開始時以同步方式執行。在 async 方法內部,await 關鍵字 對它的引數執行乙個非同步等待。它首先檢查操作是否已經完成,如果完成了,就繼續執行 (同步方式)。否則,它會暫停 async 方法,並返回,留下乙個未完成的 task。一段時間後, 操作完成,async 方法就恢復執行。 不會阻塞ui執行緒 ,await方法完成自動的通知他 然後執行剩餘的**,非同步是為了程式本身不卡 呼叫處還是非同步的 呼叫處下面的**還是會先執行 await實際上只是把主線程釋放了,使用了其他執行緒代替他繼續 非同步不是為了讓請求更快,而是為了可以處理更多請求

非同步有乙個核心,是task。而task有乙個方法,就是wait,寫法是task.wait()。所以,很多人把這個wait和await混為一談,這是錯的。

尤其,task.wait()是乙個同步方法,用於多執行緒中阻塞等待。

用task.wait()來實現同步方法中呼叫非同步方法,這個用法本身就是錯誤的。 非同步不是多執行緒,而且在多執行緒中,多個task.wait()使用也會死鎖,也有解決和避免死鎖的一整套方式。

task.wait()是乙個同步方法,用於多執行緒中阻塞等待,不是實現同步方法中呼叫非同步方法的實現方式。

在非同步中,await表達的意思是:當前執行緒/方法中,await引導的方法出結果前,跳出當前執行緒/方法,從呼叫當前執行緒/方法的位置,去執行其它可能執行的執行緒/方法,並在引導的方法出結果後,把執行點拉回到當前位置繼續執行;直到遇到下乙個await,或執行緒/方法完成返回,跳回去剛才外部最後執行的位置繼續執行。

從 .net framework 4.5 開始,任何使用 async/await 進行修飾的方法,都會被認為是乙個非同步方法;實際上,這些非同步方法都是基於佇列的執行緒任務,從你開始使用 task 去執行一段**的時候,實際上就相當於開啟了乙個執行緒,預設情況下,這個執行緒數由執行緒池 threadpool 進行管理的。

執行緒安全的訪問方式可以通過lock來進行唯一執行緒限定,但如果使用await等待task完成,則task中不允許使用lock。

因此採用另外一種方式完成

呼叫

鎖的引入,帶來了一定的開銷和效能的損耗,並降低了程式的擴充套件性,而且還會有死鎖的發生(雖說概率不大,但也不能不防啊),因此:使用lock進行併發程式設計顯然不太適用。

還好,微軟一直在更新自己的東西:

.net framework 4提供了新的執行緒安全和擴充套件的併發集合,它們能夠解決潛在的死鎖問題和競爭條件問題,因此在很多複雜的情形下它們能夠使得並行**更容易編寫,這些集合盡可能減少使用鎖的次數,從而使得在大部分情形下能夠優化為最佳效能,不會產生不必要的同步開銷。

concurrentqueue 佇列

concurrentqueue 是完全無鎖的,能夠支援併發的新增元素,先進先出。下面貼**,詳解見注釋:

class

program

private

static concurrentqueue_concurrenproducts

/*coder:天才臥龍

* **中 建立三個併發執行緒 來操作_products 和 _concurrenproducts 集合,每次新增 10000 條資料 檢視 一般佇列queue 和 多執行緒安全下的佇列concurrentqueue 執**況

*/static

void main(string

args)

);/*建立任務 t2 t2 執行 資料集合新增操作

*/task t2 = task.factory.startnew(() =>);

/*建立任務 t3 t3 執行 資料集合新增操作

*/task t3 = task.factory.startnew(() =>);

task.waitall(t1, t2, t3);

swtask.stop();

console.writeline(

"list當前資料量為:

" +_products.count);

console.writeline(

"list執行時間為:

" +swtask.elapsedmilliseconds);

thread.sleep(

1000

); _concurrenproducts = new concurrentqueue();

stopwatch swtask1 = new

stopwatch();

swtask1.start();

/*建立任務 tk1 tk1 執行 資料集合新增操作

*/task tk1 = task.factory.startnew(() =>);

/*建立任務 tk2 tk2 執行 資料集合新增操作

*/task tk2 = task.factory.startnew(() =>);

/*建立任務 tk3 tk3 執行 資料集合新增操作

*/task tk3 = task.factory.startnew(() =>);

task.waitall(tk1, tk2, tk3);

swtask1.stop();

console.writeline(

"concurrentqueue當前資料量為:

" +_concurrenproducts.count);

console.writeline(

"concurrentqueue執行時間為:

" +swtask1.elapsedmilliseconds);

console.readline();

}/*執行集合資料新增操作

*//*

執行集合資料新增操作

*/static

void

addproducts()

});}

/*執行集合資料新增操作

*/static

void

addconcurrenproducts());}

}class

product

public

string category

public

int sellprice

}

從執行時間上來看,使用 concurrentqueue 相比 lock 明顯快了很多!

1.blockingcollection與經典的阻塞佇列資料結構類似,能夠適用於多個任務新增和刪除資料,提供阻塞和限界能力。

2.concurrentbag提供物件的執行緒安全的無序集合

3.concurrentdictionary提供可有多個執行緒同時訪問的鍵值對的執行緒安全集合

4.concurrentqueue提供執行緒安全的先進先出集合

5.concurrentstack提供執行緒安全的後進先出集合

C 非同步程式設計與多執行緒程式設計

c 5.0推出了非同步程式設計,通過關鍵字async 和 await及返回型別為task 無返回值的非同步方法 和task 返回值為t的非同步方法 可以將方法封裝為非同步方法。呼叫非同步方法時,遇到await關鍵字程式會立即返回到呼叫者,直到await後的方法執行完成。包括兩種非同步方式 i o繫結...

C 多執行緒 非同步程式設計與併發伺服器

一 多執行緒和非同步的區別 多執行緒和非同步操作兩者都可以達到避免呼叫執行緒阻塞的目的。但是,多執行緒和非同步操作還是有一些區別的。而這些區別造成了使用多執行緒和非同步操作的時機的區別。當需要執行i o操作時,使用非同步操作比使用執行緒 同步 i o操作更合適。i o操作不僅包括了直接的檔案 網路的...

多執行緒併發程式設計

docker 可謂是開啟了容器化技術的新時代,現在無論大中小公司基本上都對容器化技術有不同程度的嘗試,或是已經進行了大量容器化的改造。伴隨著 kubernetes 和 cloud native 等技術和理念的普及,也大大增加了業務容器化需求。而這一切的推進,不可避免的技術之一便是構建容器映象。在本場...