日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

第13章 C#中的多线程

發布時間:2024/1/17 C# 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第13章 C#中的多线程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

13多線程

13.1 線程概述

計算機的操作系統多采用多任務和分時設計。多任務是指在一個操作系統中開以同時運行多個程序。例如,可以在使用QQ聊天的同時聽音樂,即有多個獨立的任務,每個任務對應一個進程,每個進程也可產生多個線程。

13.1.1 進程

認識進程先從程序開始,程序(Program)是對數據描述與操作的代碼的集合,如Office中的Word,影音風暴等應用程序。

進程(Process)是程序的一次動態執行過程,它對應了從代碼加載、執行至執行完畢的一個完整過程,這個過程也是進程本身從產生、發展直至消亡的過程。操作系統同時管理一個計算機系統中的多個進程,讓計算機系統中的多個進程輪流使用CPU資源,或者共享操作系統的其它資源。

進程的特定是:

  • 進程是系統運行程序的基本單位
  • 每一個進程都有自己獨立的一塊內存空間、一組系統資源。
  • 每一個進程的內部數據和狀態都是完全獨立的。

在操作系統中可以有多個進程,這些進程包括系統進程(由操作系統內部建立的進程)和用戶進程(由用戶程序建立的進程)。可以從Windows任務管理器中查看已啟動的進程。圖13-1中標注了已啟動的Office Word進程。

?

13-1 Windows任務管理器中的Office World進程

13.1.2 線程

線程是進程中執行運算的最小單位,可完成一個獨立的順序控制流程。每個進程中,必須至少建立一個線程(這個線程稱為主線程)來作為這個程序運行的入口點。如果在一個進程中同時運行了多個線程,用來完成不同的工作,則稱之為"多線程"。在操作系統將進程分成多個線程后,實際上每個任務是一個線程,多個線程共享相同的地址空間并且共同分享同一個進程,這些線程可以在操作系統的管理下并發執行。從而大大提高了程序的運行效率。雖然線程的執行看似是多個線程同時執行,但實際上并非如此。由于單CPU的計算機中,CPU同時只能執行一條指令,因此,在僅有一個CPU的計算機上不可能同時執行多個任務。而操作系統為了能提高程序的運行效率,將CPU的執行時間分成多個時間片,分配給不同的線程,當一個時間片執行完畢后,該線程就可能讓出CPU使用權限交付給下一個時間片的其它線程執行。當然有可能相鄰的時間片分配給同一線程。之所以表面上看是多個線程同時執行,是因為不同線程之間切換的時間非常短,也許僅僅是幾毫秒,對普通人來說是難以感知的,這樣就看似多個線程在同時執行了。

為了更好地了解線程,下面舉一個通俗的例子。張平是某互聯網公司的開發人員,有時工作比較單一,僅是開發項目,寫代碼,這就好像程序只執行一個線程。在單線程環境中,每個程序執行的方式是只有一個處理順序。但對開發人員來說,這只是一種理想的狀態,有時還需要兼顧其它工作,如修改Bug,參與技術交流、編寫項目文檔,和其它部門同時溝通項目需求等。項目經理一般會希望張平一天內多項工作都會有進展,但是在同一時間,張平只能做一個項目工作。這就好像程序開啟了多個線程,可以處理多個不同任務,但是CPU在同一時刻,只能執行該進程的一個線程。

13.1.3 多線程的好處

多線程作為一種多任務并發的工作方式,有著廣泛的應用,合理地使用線程,將減少開發和維護的成本,甚至可以改善復雜應用程序的性能。使用多線的優勢如下。

  • 充分利用CPU的資源:執行單線程程序時,若程序發生阻塞,CPU可能會處于空閑狀態,這將造成計算機資源浪費,而使用多線程可以在某個線程處理休眠或阻塞狀態時運行其它線程,這樣,大大提高了資源利用率。
  • 簡化編程模型:一個既長又復雜的進程可以考慮分為多個線程,成為幾個獨立的運行部分,如使用時、分、秒來描述當前時間,如果寫成單線程程序可能需要多循環判斷,而如果使用多線程,時、分、秒各使用一個線程控制,每個線程僅需實現簡單的流程,簡化了程序邏輯,這樣更有助于開發人員對程序的理解和維護。
  • 帶來良好的用戶體驗:由于多個線程可以交替執行,減少或避免了因程序阻塞或意外情況造成的響應過慢現象,降低了用戶等待的幾率。

13.2 C#中實現多線程

.NET中,Thread類將線程所必需的功能做了封裝,位于System.Threading命名空間。

13.2.1 主線程

在程序啟動時,一個線程立刻運行,該線程通常稱為程序的主線程。程序的Main()方法是主線程的入口。每個進程都至少有一個主線程。它是程序開始時就執行的。主線程的重要性體現在以下兩方面。

  • 它是產生其它子線程的線程
  • 通常它必須最后完成執行,因為它執行各種關閉動作。

盡管主線程在程序啟動時自動創建,但它可以由一個Thread對象控制。下面的實例1顯示如何引用主線程。

示例1

???? static void Main(string[] args)
????{
????????//
判斷當前線程是否已經命名
????????if (Thread.CurrentThread.Name == null)
????????{
????????????Thread.CurrentThread.Name = "MainThread";
????????}
????????Console.WriteLine("
當前線程的名稱為:"+Thread.CurrentThread.Name);
????}

在實例1中,Thread類的CurrentThread靜態屬性可以獲得當前主線程對象,線程對象的Name屬性表示線程的名稱,此屬性默認值為null,且只可賦值一次。如果第二次賦值,則會引發異常,故在實例1中先判斷線程對象是否已經命名。程序運行結果如圖13-2所示。

?

?

13-2 顯示當前線程名稱

開發中,用戶編寫的線程一般是指除了主線程之外的其它線程。使用一個線程的過程可以分為以下三個步驟。

1)定義一個線程對象,同時指明這個線程所要執行的代碼,即期望完成的功能。

2)啟動線程。

3)終止線程。

13.2.2 創建線程

下面來編寫代碼,創建兩個線程,在線程中輸出1~100的整數。

實例2

static void Main(string[] args)
{
//
創建第一個線程對象
Thread thread1 = new Thread(DoWork);
thread1.Name = "myThread1";
//
創建第二個線程對象
Thread thread2 = new Thread(DoWork);
thread2.Name = "myThread2";
//
啟動線程
thread1.Start();
thread2.Start();
}
//
線程要調用的方法
static void DoWork()
{
for(int i=1;i<=100;i++)
{
Console.WriteLine(Thread.CurrentThread.Name+":"+i);
}
}

實例2中,通過Thread類的構造函數創建線程對象,Thread的構造函數形式的如下:

public Thread(ThreadStart start);

其參數start的類型ThreadStart是一個委托。表示要執行的方法。

Thread對象的Start()方法用來啟動線程。程序運行結果如圖13-3所示。

?

?

13-3 創建線程并啟動

通過圖13-3的結果可以看出,兩個線程對象調用Start()方法后,各自都會輸出100以內的整數,互不影響,并行執行。在.NET中每個線程都有自己獨立的內存棧,所以每個線程的本地變量都相互獨立。但由于CPU在一個時間點只能執行一個線程,因此多個線程是交替執行的,獲得CPU時間片的線程即刻執行,當前時間片執行完畢后,CPU就會執行獲得下一個時間片的線程。分配的時間片長度不是完全一致的,可多可少,因此每次運行的結果有所不同,總之,是輪換交替執行的。

13.3 線程的狀態

任何線程一般都具有五種狀態,即創建、就緒、運行、阻塞、死亡狀態。線程狀態的轉移與方法之間的關系如圖13-4所示。

?

?

13-4 線程狀態的轉移與方法之間的關系

  • 創建狀態
    在程序中創建一個線程對象后,新的線程對象就處于創建狀態,此時,他已經獲取了相應的資源,但還沒有處于可運行的狀態,這時可以設置
    Thread對象的屬性,如線程名稱、優先級等。
  • 就緒狀態
    線程創建之后,就可以通過調用
    Start()方法啟動線程,即進入就緒狀態。此時,線程將進入線程隊列排隊,等待CPU資源,這表明它已經具備了運行條件,在未獲得CPU資源時,仍不能真正執行。舉例來說,去醫院看病,某主任的專家號每天只有20個,掛上號的患者還需在分診處等待叫號。這里每個掛到專家號的患者可以看成一個就緒狀態的線程。
  • 運行狀態
    當就緒狀態的線程獲得
    CPU資源時,即可轉入運行狀態。對只有一個CPU的計算機而言,任何時刻只能有一個處于運行狀態的線程占用CPU,即獲得CPU資源。延續上面醫院看病的例子,被叫到的患者才能真正就診,而每個主任專家在一個時刻只能為一個患者看病。
  • 阻塞狀態
    一個正在運行的線程因某種原因不能繼續運行時,進入阻塞狀態。阻塞狀態是一種"不可運行"的狀態,而處于這種狀態的線程在得到一個特定的事件之后會轉回可運行狀態。舉例來說,輪到小張看病了,醫生為查明原因要求他去做個化驗,醫生得到化驗結果后才能繼續診斷,如果把醫生給小張看病看作一個線程,則該線程此時即處于阻塞狀態。
    可能使線程暫停執行的條件如下。
    • 由于線程優先級比較低,因此它不能獲得CPU資源。
    • 使用Sleep()方法使線程休眠。
    • 通過調用Wait()方法,使線程等待。
    • 通過調用Yield()方法,線程顯示出讓CPU控制權。
    • 線程由于等待一個文件,I/O事件被阻塞。
  • 死亡狀態
    一個線程運行完畢,線程則進入死亡狀態。處于死亡狀態的線程不具有繼續運行的能力。

13.4 線程的調度
在單CPU的計算機中,一個時刻只有一個線程運行,所謂多線程的并發運行,其實是指從宏觀上看,各個線程輪流獲得CPU資源的使用權,分別執行各自的任務。.NET Framework可以對線程進行調度。線程調度是指按照特定機制為多個線程分配CPU的使用權。
13.4.1
線程的優先級
當同一時刻有一個或多個線程處于運行狀態時,它們需要排隊等待CPU資源,每個線程會自動獲得一個線程的優先級(Priority),優先級的高低反映線程的重要或緊急程度。那么此刻,一般情況下優先級高的線程獲得CPU資源的概率較大,但這個結果不是絕對的,線程優先級調度是一個復雜的過程。
Thread
對象可以通過Priority屬性(枚舉類型)設置線程的優先級,優先級從低到高的五個取值為LowestBelowNormalNormalAboveNormalHighest
我們對實例2中的代碼進行修改,分別設置連個線程的優先級,如實例3所示。
實例3
static void Main(string[] args)
{
//
創建第一個線程對象
Thread thread1 = new Thread(DoWork);
thread1.Name = "myThread1";
//
創建第二個線程對象
Thread thread2 = new Thread(DoWork);
thread2.Name = "myThread2";
//
設置線程的優先級
thread1.Priority = ThreadPriority.Highest;
thread2.Priority = ThreadPriority.Lowest;
//
啟動線程
thread1.Start();
thread2.Start();
}
//
線程要調用的方法
static void DoWork()
{
for(int i=1;i<=100;i++)
{
Console.WriteLine(Thread.CurrentThread.Name+":"+i);
}
}
運行結果如圖13-5所示。

?

?

13-5 線程的優先級

從圖13-5中看出,優先級高的thread1對象優先執行完成。
13.4.2 線程的休眠
在程序中允許一個線程進行暫時休眠,直接使用
Thread.Sleep()方法即可實現線程的休眠。Sleep()方法的定義語法如下。
public static void Sleep(int millisecondsTimeout)
參數表示休眠時長,單位為毫秒。線程由運行中的狀態進入不可運行狀態,睡眠時間過后線程會再次進入可運行狀態。
實例
4模擬主線程休眠五秒后開始執行。
實例
4
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Wait");
WaitBySec(5); //
讓主線程等待5秒再執行
Console.WriteLine("Start");
}

public static void WaitBySec(int s)
{
for(int i=0;i<s;i++)
{
Console.WriteLine(i+1+"
");
Thread.Sleep(1000); //
睡眠1
}
}
}
運行結果如圖13-6所示。

?

?

13-6 線程的休眠

13.4.3 線程的強制運行

Join()方法使當前線程暫停執行,等待調用該方法的線程結束后再繼續執行本線程。

下面通過實例來具體看一下Join()方法的應用。實例5為使用Join()方法阻塞線程的案例。

實例5

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

class Program

{

static void Main(string[] args)

{

Console.WriteLine("*********線程強制執行**********");

//創建子線程并啟動

Thread temp = new Thread(DoWork);

temp.Name = "MyThread1";

temp.Start();

for(int i=0;i<20;i++)

{

if (i == 5)

temp.Join(); //阻塞主線程,子線程強制執行

Thread.Sleep(100);

Console.WriteLine("主線程運行:"+i);

}

Console.ReadKey();

}

static void DoWork()

{

for(int i=1;i<=10;i++)

{

Thread.Sleep(100); //增加線程交替執行的幾率

Console.WriteLine(Thread.CurrentThread.Name+":"+i);

}

}

}

在示例5中,主線程的i的值為5時,子線程調用Join()方法,阻塞主線程,子線程強制執行,直到子線程運行完畢后,主線程才能繼續執行。運行結果如圖13-7所示。

?

?

13-7 線程的強制執行

13.4.4 線程的禮讓

Yield()方法定義的語法如下。

public static bool Yield();

Yield()方法可暫停當前線程執行,允許其它具有相同優先級的線程獲得運行機會,該線程仍處于就緒狀態,不轉為阻塞狀態,此時,系統選擇其它相同或更高優先級線程執行。若無其它相同或更高優先級線程,則該線程繼續執行。返回值為bool類型,如果操作系統轉而執行另一個線程,則為 true;否則為 false。示例6實現了兩個線程之間的禮讓。

注意

使用Yield()的線程禮讓只是提供一種可能,但是不能保證一定會禮讓,因為禮讓的線程處于就緒狀態,還有可能被線程調度程序再次選中。

示例6

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

class Program

{

static void Main(string[] args)

{

Thread thA = new Thread(DoWork);

thA.Name = "線程A";

Thread thB = new Thread(DoWork);

thB.Name = "線程B";

thA.Start();

thB.Start();

Console.ReadKey();

}

static void DoWork()

{

for(int i=0;i<5;i++)

{

Console.WriteLine(Thread.CurrentThread.Name+"正在運行:"+i);

if (i==3)

{

Console.Write("線程禮讓:");

Thread.Yield();

}

}

}

}

運行結果如圖13-8所示

?

?

13-8 線程的禮讓

從程序的運行結果中可以放發現,每當線程滿足條件(i==3)時,建議當前線程暫停,而讓其它線程先執行,當然,這僅是提供一種可能。

13.5 線程的同步

13.5.1 多線程共享數據引發的問題

前面學習的線程都是獨立的,而且異步執行,也就是說每個線程都包含了運行時所需要的數據或方法,而不需要外部資源或方法,也不必關心其它線程的狀態和行為。但是經常有一些同時運行的線程需要共享數據,此時就需要考慮其它線程的狀態和行為,否則不能保證程序運行結果的正確性。

舉個例子來說,我們都熟悉每年春運搶票的場景。以前需要親自到火車站或者售票點排隊買票,火車站每個車次會定期定量發放車票,先到先得。現在互聯網越來越發達,可以網上買票了,這樣又多了一個更加方便的購票渠道。現在,我們使用多線程來模擬多人買票的過程。每個人搶到票的機會均等,這樣,可以把每一個看作是一個線程,購票過程是線程的執行體,而每售出一張票,總票數就會減少,因此注意,預發售的火車票總數是多線程所共同操作的數據。假定現在有三個人搶十張票,實現思路如下。

1)定義類Site模擬售票網站。發放固定車次的車票,這里為簡化過程,設定預出售的車票總共十張,定義變量Count記錄剩余票數,變量Num記錄當前售出第幾張票。

2實現售票方法SaleTicket()。網站將持續提供售票服務,因此,這里使用到循環語句,Count作為循環變量。在循環體中,當還有余票時,購票過程分為以下兩步。

第一步,修改數據,指當前售票序號(Num)以及剩余票數(Count)

第二步,顯示售票信息。

在兩步之間,為模擬網絡延遲,使用Sleep()方法設置線程休眠500毫秒。

3)定義測試類模擬多人搶票。創建三個線程,指定線程名稱,并啟動線程。

代碼如示例7所示。

示例7

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

public class Site

{

int Count = 10; //記錄剩余票數

int Num = 0; //記錄買到第幾張票

//售票方法

public void SaleTicket()

{

while(true)

{

//沒有余票時跳出循環

if (Count <= 0)

break;

//第一步:修改數據

Num++;

Count--;

Thread.Sleep(500); //模擬網絡延時

//第二步:顯示信息

Console.WriteLine("{0}搶到第{1}票,剩余{2}票!",

Thread.CurrentThread.Name,Num,Count);

}

}

}

//測試類Main()方法

static void Main(string[] args)

{

Site site = new Site();

Thread person1 = new Thread(site.SaleTicket);

person1.Name = "王小毛";

Thread person2 = new Thread(site.SaleTicket);

person2.Name = "搶票代理";

Thread person3 = new Thread(site.SaleTicket);

person3.Name = "黃牛黨";

person1.Start();

person2.Start();

person3.Start();

}

示例7中,Main()方法中創建三個線程模擬三人開始搶票,并且啟動線程。運行結果如圖13-9所示。

?

?

13-9 多線程模擬網絡購票

從圖13-8中發現,最終顯示結果存在以下問題。

  • 不是從第一張票開始。
  • 存在多人搶到一張票的情況。
  • 有些票號沒有被搶到。

這是由于多線程并發執行操作同一共享資源時,將帶來數據不安全問題。例如,在上述案例中。三個人共同搶票,各自執行完第一步修改數據,此時等待網絡延時,再執行第二步顯示信息時,由于前面修改了三次數據后Count值為7Num值為3,最終顯示三個人都搶到了第三張票。這當然僅僅是一種情況。

要解決此類問題,就需要保證一個人在搶票過程未結束前,不允許其他人同時搶票。這在開發中,就需要使用線程同步。

注意

示例7中提出的問題僅在多線程共享統一資源時產生,如三人共搶十張票;反之,在不存在資源共享時無需考慮此類問題。

13.5.2 線程同步的實現

當兩個或多個線程需要訪問同一資源時,需要以某種順序來確保該資源某一時刻只能被一個線程使用,這就稱為線程同步。

C#中,我們可以通過lock語句實現線程同步。

資料

C#中實現線程的同步有幾種方法:lockMutexMonitorSemaphoreInterlockedReaderWriterLock等。同步策略也可以分為同步上下文、同步代碼區、手動同步幾種方式。大家可以查閱MSDN自行學習。

lock 關鍵字將語句塊標記為臨界區,方法是獲取給定對象的互斥鎖,執行語句,然后釋放該鎖。lock 確保當一個線程位于代碼的臨界區時,另一個線程不進入臨界區。如果其他線程試圖進入鎖定的代碼,則它將一直等待(即被阻止),直到該對象被釋放。其語法如下:

lock(locker)
{
//
需要同步的代碼
}

提供給 lock 關鍵字的參數locker必須為基于引用類型的對象,該對象用來定義鎖的范圍,可以是任意類實例。

針對示例7的情況,我們用lock語句完成線程同步。如實例8所示

示例8

public class Site
{
int Count = 10; //
記錄剩余票數
int Num = 0; //
記錄買到第幾張票
//
定義鎖定對象
private object locker = new object();

public void SaleTicket()
{
while(true)
{
lock (locker)
{
//
沒有余票時跳出循環
if (Count <= 0)
break;
//
第一步:修改數據
Num++;
Count--;
Thread.Sleep(500); //
模擬網絡延時
//
第二步:顯示信息
Console.WriteLine("{0}
搶到第{1}票,剩余{2}票!",
Thread.CurrentThread.Name, Num, Count);
}
}
}

}

當同步對共享資源的線程訪問時,請鎖定專用對象實例(例如,private object locker = new object();)或另一個不太可能被代碼無關部分用作 lock 對象的實例。避免對不同的共享資源使用相同的 lock 對象實例,因為這可能導致死鎖或鎖爭用。具體而言,避免將以下對象用作 lock 對象:

  • this(調用方可能將其用作 lock)。
  • Type 實例(可以通過 typeof 運算符或反射獲取)。
  • 字符串實例,包括字符串文本。

運行結果如圖13-10所示。

?

?

13-10 使用線程同步的網絡購票

13.5.3 線程安全的類型

若所在的進程中有多個線程在同時運行,而這些線程同時運行這段代碼。如果每次運行結果和單線程運行的結果是一樣的,而且其他的變量的值也和預期的是一樣的,就是線程安全的。

一個類在被多個線程訪問時,不管運行時環境執行這些線程有什么樣的時序安排,它必須是以固定的、一致的順序執行。這樣的類型稱為線程安全的類型。

ArrayList集合為例,在向ArrayList對象添加一個元素的時候,由兩步來完成:

1)將索引值加1,即為集合擴容,確保可裝入新元素。

2)在新增位置存放數據。

Add()方法是非線程安全的,如有線程A和線程B向同一個ArrayList對象中添加元素,兩個線程同時獲得Count值為5,之后同時執行完加1操作再賦值給Count,兩個線程為同一個位置元素賦值,后一個覆蓋前一個,引發數據不安全問題。說明ArrayList是非線程安全的類型。

資料

ArrayList類可以通過Synchronized()方法用來得到一個線程安全的ArrayList對象,語法如下:

ArrayList arr = ArrayList.Synchronized(new ArrayList());

另外Hashtable也有類似的方法。

.Net 4,新增System.Collections.Concurrent 命名空間中提供多個線程安全集合類,這些類提供了很多有用的方法用于訪問集合中的元素,從而可以避免使用傳統的鎖(lock)機制等方式來處理并發訪問集合。因此當有多個線程并發訪問集合時,應首先考慮使用這些類代替 System.Collections System.Collections.Generic 命名空間中的對應類型。具體如下。

1.ConcurrentQueue

表示線程安全的先進先出 (FIFO) 集合。Enqueue(T) 方法用于將對象添加到 ConcurrentQueue 的結尾處。

2.ConcurrentStack

表示線程安全的后進先出 (LIFO) 集合。 ConcurrentStack 提供了幾個主要操作:

  • Push 在頂部插入一個元素ConcurrentStack
  • TryPop 從頂部移除一個元素ConcurrentStack,或返回false如果不能刪除該項。
  • TryPeek 返回位于頂部的元素ConcurrentStack但不會刪除從ConcurrentStack
  • TryPopRangePushRange方法提供了有效推送和彈出的單個操作中的多個元素。

3.ConcurrentBag

表示對象的線程安全的無序集合。 Add(T)方法用于將對象添加到 ConcurrentBag 中。

4.ConcurrentDictionary

Dictionary類似,表示可由多個線程同時訪問的鍵/值對的線程安全集合。 常用方法如下:

  • TryAdd(TKey, TValue) :嘗試將指定的鍵和值添加到 ConcurrentDictionary 中。
  • TryGetValue(TKey, TValue) :嘗試從 ConcurrentDictionary 獲取與指定的鍵關聯的值。
  • TryRemove(TKey, TValue) :嘗試從 ConcurrentDictionary 中移除并返回具有指定鍵的值。
  • TryUpdate(TKey, TValue, TValue) :如果具有 key 的現有值等于 comparisonValue,則將與 key 關聯的值更新為 newValue

通過上述提供的安全類,我們可以方便的并發訪問集合中的元素,而不需要以前的Synchronized方法或者lock(SyncRoot)等處理方式。

在多線程操作中,需要選擇線程安全的類型或通過同步操作避免多個線程共享資源時引發的問題,但線程的同步也會損失性能,因此,為達到安全性和效率的平衡,可根據實際場景來選擇合適的類型。

轉載于:https://www.cnblogs.com/mrfang/p/10880587.html

總結

以上是生活随笔為你收集整理的第13章 C#中的多线程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。