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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第二节:深入剖析Thread的五大方法、数据槽、内存栅栏

發(fā)布時間:2023/12/10 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第二节:深入剖析Thread的五大方法、数据槽、内存栅栏 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一. Thread及其五大方法

?  Thread是.Net最早的多線程處理方式,它出現(xiàn)在.Net1.0時代,雖然現(xiàn)在已逐漸被微軟所拋棄,微軟強烈推薦使用Task(后面章節(jié)介紹),但從多線程完整性的角度上來說,我們有必要了解下N年前多線程的是怎么處理的,以便體會.Net體系中多線程處理方式的進化。

  Thread中有五大方法,分別是:Start、Suspend、Resume、Intterupt、Abort

  ①.Start:開啟線程

  ②.Suspend:暫停線程

  ③.Resume:恢復(fù)暫停的線程

  ④.Intterupt:中斷線程(會拋異常,提示線程中斷)

  ⑤.Abort:銷毀線程

?  ?這五大方法使用起來,也比較簡單,下面貼一段代碼,體會一下如何使用即可。

?

  在這里補充一下,在該系列中,很多測試代碼中看到TestThread0、TestThread、TestThread2,分別對應(yīng)無參、一個參數(shù)、兩個參數(shù)的耗時方法,代碼如下:

?View Code

?

二. 從源碼角度分析Thread類

(1) ?分析Thread類的源碼,發(fā)現(xiàn)其構(gòu)造函數(shù)有兩類,分別是ThreadStart和ParameterizedThreadStart類,

 其中

  ①:ThreadStart類,是無參無返回值的委托。

  ②:ParameterizedThreadStart類,是有一個object類型參數(shù)但無返回值的委托.

使用方法:

  ①:針對ThreadStart類, ThreadStart myTs = () => TestThread(name); ?然后再把myTs傳入Thread的構(gòu)造函數(shù)中

  ②:針對ParameterizedThreadStart類,ParameterizedThreadStart myTs = o => this.TestThread(o.ToString()); ?然后再把myTs傳入Thread的構(gòu)造函數(shù)中

  注:該方式存在拆箱和裝箱的轉(zhuǎn)換問題,不建議這么使用

通用寫法

?    Thread t = new Thread(() =>

    {

?      Console.Write("333");

    });

    t.Start();

無須考慮Thread的構(gòu)造函數(shù),也不需要考慮Start的時候傳參,直接使用()=>{}的形式,解決一切問題。

(二) 前臺進程和后臺進程(IsBackground屬性)

  ①:前臺進程,Thread默認為前臺線程,程序關(guān)閉后,線程仍然繼續(xù),直到計算完為止

  ②:后臺進程,將IsBackground屬性設(shè)置為true,即為后臺進程,主線程關(guān)閉,所有子線程無論運行完否,都馬上關(guān)閉

(三) 線程等待(Join方法)

  利用Join方法實現(xiàn)主線程等待子線程,當多個子線程進行等待的時候,只能通過for循環(huán)來實現(xiàn)

?下面貼一下這三塊設(shè)計到的代碼:

?

?View Code

(四). 擴展:Thread實現(xiàn)線程回調(diào)

?

三. 數(shù)據(jù)槽-線程可見性

  背景:為了解決多線程競用共享資源的問題,引入數(shù)據(jù)槽的概念,即將數(shù)據(jù)存放到線程的環(huán)境塊中,使該數(shù)據(jù)只能單一線程訪問.(屬于線程空間上的開銷)

  下面的三種方式是解決多線程競用共享資源的通用方式:

  ①:AllocateNamedDataSlot命名槽位和AllocateDataSlot未命名槽位 解決線程競用資源共享問題。

  (PS:在主線程上設(shè)置槽位,使該數(shù)據(jù)只能被主線程讀取,其它線程無法訪問)

?

private void button10_Click(object sender, EventArgs e){#region 01-AllocateNamedDataSlot命名槽位{var d = Thread.AllocateNamedDataSlot("userName");//在主線程上設(shè)置槽位,使該數(shù)據(jù)只能被主線程讀取,其它線程無法訪問Thread.SetData(d, "ypf");//聲明一個子線程var t1 = new Thread(() =>{Console.WriteLine("子線程中讀取數(shù)據(jù):{0}", Thread.GetData(d));});t1.Start();//主線程中讀取數(shù)據(jù)Console.WriteLine("主線程中讀取數(shù)據(jù):{0}", Thread.GetData(d));}#endregion#region 02-AllocateDataSlot未命名槽位{var d = Thread.AllocateDataSlot();//在主線程上設(shè)置槽位,使該數(shù)據(jù)只能被主線程讀取,其它線程無法訪問Thread.SetData(d, "ypf");//聲明一個子線程var t1 = new Thread(() =>{Console.WriteLine("子線程中讀取數(shù)據(jù):{0}", Thread.GetData(d));});t1.Start();//主線程中讀取數(shù)據(jù)Console.WriteLine("主線程中讀取數(shù)據(jù):{0}", Thread.GetData(d));}#endregion}

?

  ②:利用特性[ThreadStatic] 解決線程競用資源共享問題

?  (PS:在主線程中給ThreadStatic特性標注的變量賦值,則只有主線程能訪問該變量)

  ③:利用ThreadLocal線程的本地存儲, 解決線程競用資源共享問題(線程可見性)

  (PS:?在主線程中聲明ThreadLocal變量,并對其賦值,則只有主線程能訪問該變量)

?

?

四. 內(nèi)存柵欄-線程共享資源

背景:當多個線程共享一個變量的時候,在Release模式的優(yōu)化下,子線程會將共享變量加載的cup Cache中,導致主線程不能使用該變量而無法運行。

解決方案:

  ①:不要讓多線程去操作同一個共享變量,從根本上解決這個問題。

  ②:利用MemoryBarrier方法進行處理,在此方法之前的內(nèi)存寫入都要及時從cpu cache中更新到 memory;在此方法之后的內(nèi)存讀取都要從memory中讀取,而不是cpu cache。

  ③:利用VolatileRead/Write方法進行處理。

1 private void button11_Click(object sender, EventArgs e)2 {3 #region 01-默認情況(Release模式主線程不能正常運行)4 //{5 // var isStop = false;6 // var t = new Thread(() =>7 // {8 // var isSuccess = false;9 // while (!isStop) 10 // { 11 // isSuccess = !isSuccess; 12 // } 13 // Console.WriteLine("子線程執(zhí)行成功"); 14 // }); 15 // t.Start(); 16 17 // Thread.Sleep(1000); 18 // isStop = true; 19 20 // t.Join(); 21 // Console.WriteLine("主線程執(zhí)行結(jié)束"); 22 //} 23 #endregion 24 25 #region 02-MemoryBarrier解決共享變量(Release模式下可以正常運行) 26 //{ 27 // var isStop = false; 28 // var t = new Thread(() => 29 // { 30 // var isSuccess = false; 31 // while (!isStop) 32 // { 33 // Thread.MemoryBarrier(); 34 35 // isSuccess = !isSuccess; 36 // } 37 // Console.WriteLine("子線程執(zhí)行成功"); 38 // }); 39 // t.Start(); 40 41 // Thread.Sleep(1000); 42 // isStop = true; 43 44 // t.Join(); 45 // Console.WriteLine("主線程執(zhí)行結(jié)束"); 46 //} 47 #endregion 48 49 #region 03-VolatileRead解決共享變量(Release模式下可以正常運行) 50 { 51 var isStop = 0; 52 var t = new Thread(() => 53 { 54 var isSuccess = false; 55 while (isStop == 0) 56 { 57 Thread.VolatileRead(ref isStop); 58 59 isSuccess = !isSuccess; 60 } 61 Console.WriteLine("子線程執(zhí)行成功"); 62 }); 63 t.Start(); 64 65 Thread.Sleep(1000); 66 isStop = 1; 67 68 t.Join(); 69 Console.WriteLine("主線程執(zhí)行結(jié)束"); 70 } 71 #endregion 72 73 74 }

?

?

?

總結(jié)

以上是生活随笔為你收集整理的第二节:深入剖析Thread的五大方法、数据槽、内存栅栏的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。