您好,登錄后才能下訂單哦!
我們繼續學習.NET多線程技術,這篇文章的內容可能有點復雜。在打破常理之后,換一種新的思考模型最為頭疼。這篇文章里面會涉及到一些不太常見的概念,比如:上下文、同步域等等。我也是最近才接觸這些關于組件編程方面的高深技術,大家一起學習,再大的困難也是有時間限制的,只要我們堅持。
在本人的上一篇文章“.NET簡談組件程序設計之(多線程與并發管理一)”中,只是初步的帶領我們學習一下關于多線程的一些基本的原理,包括線程切換,線程的開始、執行、等待、結束。
這篇文章的重點是學習關于線程的同步、互斥的機制。在多線程的應用程序中,最少會有一個主線程在運行著,如果我們想提高應用程序的吞吐量就必須借助多線程的原理來實現。[王清培版權所有,轉載請給出署名]
.NET上下文(ContextBoundObject對象)
什么叫上下文,千萬別和ASP.NET中的上下文搞混了,這個上下文是個形容詞,在不同的場合有不同的意思。在ASP.NET中的上下文是指Context對象,這個對象基本上包容了HTTP協議的整個生命周期的信息,可以獲取到客戶端瀏覽器的一些基本信息,也可以獲取到關于HTTP協議的一些信息,等等。
這里所講的上下文是.NET程序執行的最小邏輯范圍,ASP.NET上下文是站在B/S編程模型角度去看待的,而這里的上下文是站在.NET底層運行角度看來的,后者是代碼的上下文,前者是整個生命周期的上下文。
在沒有接觸ContextBoundObject之前我一直以為.NET程序執行的最小邏輯范圍是應用程序域(AppDomain),知道了之后才知道另有隱情,上下文是用來確定對象的邏輯歸屬,在多線程(Thread)、事物處理(Transaction)、企業服務(Enterprise)等方面都需要用上下文來對對象進行規劃。下面您將看到怎么用上下文來進行線程的同步的。
圖1:
.NET同步域(Synchronization特性)
同步域的概念是來源于多線程的場合,在我們進行多線程操作的時候,讓很多個線程去同時訪問一個內存對象的時候,是必須用鎖來保證只有一個線程進入對象操作的,那么同步域的概念就是同步的是一個區域,而不是單單的一個對象。
線程是代碼的執行路徑,只要在這條執行路徑上都屬于線程的范圍,那么怎么在執行的路徑中分離出另外一個同步區域。[王清培版權所有,轉載請給出署名]
臨界資源是系統中對同一時間只能由一個線程進行訪問的描述。我們假設自己就是一個線程,我們要去家里拿點東西,那么門就是線程的同步鎖,當我們進去的時候就把門從里面反鎖,出去的時候就把門打開,以方便自己的家人進來。這個房子就是臨界資源。可能這樣的描述不太靠譜,哪有這樣的家啊!
圖2:
利用上下文和同步域進行線程的同步
下面我們將結合上下文和同步域的原理進行線程的同步。請看一段代碼:
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Threading;
- using System.Runtime.Remoting;
- using System.Runtime.Remoting.Contexts;
- namespace ConsoleApplication1.多線程和并發管理
- {
- //如果不加上下文,那么就是以對象為線程鎖定區域,如果加上下文,那么就是已邏輯上下文為鎖定區域
- [Synchronization(SynchronizationAttribute.REQUIRED, true)]//重新進入同步域
- public class MyClass : ContextBoundObject
- {
- public void DoWork()
- {
- int i = 0;
- while (true)
- {
- Console.WriteLine(Thread.CurrentThread.ManagedThreadId + "|" + i++);
- if (i == 10)
- {
- Console.WriteLine("---------------------------------------------");
- Console.Read();
- break;
- }
- }
- }
- }
- }
在這段代碼里面,我給Myclass類加上了Synchronization特性,并且繼承自上下文對象ContextBoundObject。兩者必須集合使用,同步域只有在上下文中才有效。
【MSDN:將 SynchronizationAttribute 應用到一個上下文綁定對象會導致創建等待句柄和自動重置事件,這些內容不一定會被作為垃圾來回收。因此,不要在很短的時間內創建大量用 SynchronizationAttribute 標記的上下文綁定對象。】
圖3:
圖4:
我們來看調用代碼:
- Thread currentthread = Thread.CurrentThread;
- Console.WriteLine(currentthread.Name + currentthread.ManagedThreadId);
- MyClass myclass = new MyClass();
- Thread thread = new Thread(new ThreadStart(myclass.DoWork));
- Thread thread2 = new Thread(new ThreadStart(myclass.DoWork));
- thread2.Start();
- thread.Start();
- thread2.Join();
- thread.Join();
- Console.WriteLine(currentthread.Name + currentthread.ManagedThreadId);
- Console.Read();
圖5:
我為了方便截圖所以把循環的數字設的比較小,如果你想測試一下,可以把數字設的大一點。[王清培版權所有,轉載請給出署名]
在SynchronizationAttribute對象里面有幾個枚舉值,是用來確定是否共享一個同步域的,有興趣的可以自己嘗試,我就不在這里多講了。
總結:同步域和上下文對象是線程自動同步的好方法,但是他鎖定的目標太大,難免導致系統的吞吐量下降,所以下面幾篇文章我們將會學習怎么使用手動同步來實現更靈活的同步(Monitor、WaitHandler等),從很小的粒度進行鎖定。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。