• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            cc

              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
              38 隨筆 :: 14 文章 :: 21 評論 :: 0 Trackbacks

            以下各節描述了在多線程應用程序中可以用來同步資源訪問的功能和類。

            在應用程序中使用多個線程的一個好處是每個線程都可以異步執行。對于 Windows 應用程序,耗時的任務可以在后臺執行,而使應用程序窗口和控件保持響應。對于服務器應用程序,多線程處理提供了用不同線程處理每個傳入請求的能力。否則,在完全滿足前一個請求之前,將無法處理每個新請求。

            然而,線程的異步特性意味著必須協調對資源(如文件句柄、網絡連接和內存)的訪問。否則,兩個或更多的線程可能在同一時間訪問相同的資源,而每個線程都不知道其他線程的操作。結果將產生不可預知的數據損壞。

            對于整數數據類型的簡單操作,可以用 Interlocked 類的成員來實現線程同步。對于其他所有數據類型和非線程安全的資源,只有使用本主題中的結構才能安全地執行多線程處理。

            有關多線程編程的背景信息,請參見:

            lock 關鍵字可以用來確保代碼塊完成運行,而不會被其他線程中斷。這是通過在代碼塊運行期間為給定對象獲取互斥鎖來實現的。

            lock 語句以關鍵字 lock 開頭,它有一個作為參數的對象,在該參數的后面還有一個一次只能由一個線程執行的代碼塊。例如:

            public void Function()
            {
            System.Object lockThis = new System.Object();
            lock(lockThis)
            {
            // Access thread-sensitive resources.
            }
            }

            提供給 lock 關鍵字的參數必須為基于引用類型的對象,該對象用來定義鎖的范圍。在上例中,鎖的范圍限定為此函數,因為函數外不存在任何對該對象的引用。嚴格地說,提供給 lock 的對象只是用來唯一地標識由多個線程共享的資源,所以它可以是任意類實例。然而,實際上,此對象通常表示需要進行線程同步的資源。例如,如果一個容器對象將被多個線程使用,則可以將該容器傳遞給 lock,而 lock 后面的同步代碼塊將訪問該容器。只要其他線程在訪問該容器前先鎖定該容器,則對該對象的訪問將是安全同步的。

            通常,最好避免鎖定 public 類型或鎖定不受應用程序控制的對象實例。例如,如果該實例可以被公開訪問,則 lock(this) 可能會有問題,因為不受控制的代碼也可能會鎖定該對象。這可能導致死鎖,即兩個或更多個線程等待釋放同一對象。出于同樣的原因,鎖定公共數據類型(相比于對象)也可能導致問題。鎖定字符串尤其危險,因為字符串被公共語言運行庫 (CLR)“暫留”。這意味著整個程序中任何給定字符串都只有一個實例,就是這同一個對象表示了所有運行的應用程序域的所有線程中的該文本。因此,只要在應用程序進程中的任何位置處具有相同內容的字符串上放置了鎖,就將鎖定應用程序中該字符串的所有實例。因此,最好鎖定不會被暫留的私有或受保護成員。某些類提供專門用于鎖定的成員。例如,Array 類型提供 SyncRoot。許多集合類型也提供 SyncRoot

            有關 lock 關鍵字的更多信息,請參見:

            lock 關鍵字類似,監視器防止多個線程同時執行代碼塊。Enter 方法允許一個且僅一個線程繼續執行后面的語句;其他所有線程都將被阻止,直到執行語句的線程調用 Exit。這與使用 lock 關鍵字一樣。事實上,lock 關鍵字就是用 Monitor 類來實現的。例如:

            lock(x)
            {
            DoSomething();
            }

            這等效于:

            System.Object obj = (System.Object)x;
            System.Threading.Monitor.Enter(obj);
            try
            {
            DoSomething();
            }
            finally
            {
            System.Threading.Monitor.Exit(obj);
            }

            使用 lock 關鍵字通常比直接使用 Monitor 類更可取,一方面是因為 lock 更簡潔,另一方面是因為 lock 確保了即使受保護的代碼引發異常,也可以釋放基礎監視器。這是通過 finally 關鍵字來實現的,無論是否引發異常它都執行關聯的代碼塊。

            有關監視器的更多信息,請參見監視器同步技術示例

            使用鎖或監視器對于防止同時執行區分線程的代碼塊很有用,但是這些構造不允許一個線程向另一個線程傳達事件。這需要“同步事件”,它是有兩個狀態(終止和非終止)的對象,可以用來激活和掛起線程。讓線程等待非終止的同步事件可以將線程掛起,將事件狀態更改為終止可以將線程激活。如果線程試圖等待已經終止的事件,則線程將繼續執行,而不會延遲。

            同步事件有兩種:AutoResetEventManualResetEvent。它們之間唯一的不同在于,無論何時,只要 AutoResetEvent 激活線程,它的狀態將自動從終止變為非終止。相反,ManualResetEvent 允許它的終止狀態激活任意多個線程,只有當它的 Reset 方法被調用時才還原到非終止狀態。

            可以通過調用一種等待方法,如 WaitOneWaitAnyWaitAll,讓線程等待事件。System.Threading.WaitHandle.WaitOne 使線程一直等待,直到單個事件變為終止狀態;System.Threading.WaitHandle.WaitAny 阻止線程,直到一個或多個指示的事件變為終止狀態;System.Threading.WaitHandle.WaitAll 阻止線程,直到所有指示的事件都變為終止狀態。當調用事件的 Set 方法時,事件將變為終止狀態。

            在下面的示例中,創建了一個線程,并由 Main 函數啟動該線程。新線程使用 WaitOne 方法等待一個事件。在該事件被執行 Main 函數的主線程終止之前,該線程一直處于掛起狀態。一旦該事件終止,輔助線程將返回。在本示例中,因為事件只用于一個線程的激活,所以使用 AutoResetEventManualResetEvent 類都可以。

            using System;
            using System.Threading;
            class ThreadingExample
            {
            static AutoResetEvent autoEvent;
            static void DoWork()
            {
            Console.WriteLine("   worker thread started, now waiting on event...");
            autoEvent.WaitOne();
            Console.WriteLine("   worker thread reactivated, now exiting...");
            }
            static void Main()
            {
            autoEvent = new AutoResetEvent(false);
            Console.WriteLine("main thread starting worker thread...");
            Thread t = new Thread(DoWork);
            t.Start();
            Console.WriteLine("main thrad sleeping for 1 second...");
            Thread.Sleep(1000);
            Console.WriteLine("main thread signaling worker thread...");
            autoEvent.Set();
            }
            }

            有關線程同步事件用法的更多示例,請參見:

            mutex 與監視器類似;它防止多個線程在某一時間同時執行某個代碼塊。事實上,名稱“mutex”是術語“互相排斥 (mutually exclusive)”的簡寫形式。然而與監視器不同的是,mutex 可以用來使跨進程的線程同步。mutex 由 Mutex 類表示。

            當用于進程間同步時,mutex 稱為“命名 mutex”,因為它將用于另一個應用程序,因此它不能通過全局變量或靜態變量共享。必須給它指定一個名稱,才能使兩個應用程序訪問同一個 mutex 對象。

            盡管 mutex 可以用于進程內的線程同步,但是使用 Monitor 通常更為可取,因為監視器是專門為 .NET Framework 而設計的,因而它可以更好地利用資源。相比之下,Mutex 類是 Win32 構造的包裝。盡管 mutex 比監視器更為強大,但是相對于 Monitor 類,它所需要的互操作轉換更消耗計算資源。有關 mutex 的用法示例,請參見 Mutex

            posted on 2010-01-14 16:58 醒目西西 閱讀(270) 評論(0)  編輯 收藏 引用
            精品国产乱码久久久久久人妻| 国产福利电影一区二区三区久久老子无码午夜伦不 | 国产成人精品久久亚洲| 久久久久亚洲爆乳少妇无| 熟妇人妻久久中文字幕| 国产成人精品久久综合 | 国产精品伊人久久伊人电影 | 久久综合给合综合久久| 亚洲午夜久久久久久噜噜噜| 777久久精品一区二区三区无码| 色偷偷88欧美精品久久久| 久久精品国产清高在天天线| 久久久噜噜噜久久| 99久久人妻无码精品系列| 久久天天躁狠狠躁夜夜躁2014| 99久久精品免费看国产免费| 久久久久99精品成人片直播| 色老头网站久久网| 久久久久久亚洲精品不卡| 狠狠色噜噜狠狠狠狠狠色综合久久| 亚洲综合久久夜AV | 久久亚洲AV无码西西人体| 久久精品国产精品青草app| 亚洲AV日韩精品久久久久久| 要久久爱在线免费观看| 久久这里有精品视频| 久久久久亚洲精品中文字幕| 久久99精品久久久久久野外| AAA级久久久精品无码区| 精品久久久久久国产91| 99久久免费国产精精品| 亚洲AV无码久久精品狠狠爱浪潮| 久久精品日日躁夜夜躁欧美| 久久人人爽人人爽人人片AV东京热| 天天影视色香欲综合久久| 无码任你躁久久久久久老妇| 蜜臀久久99精品久久久久久| 人妻无码久久精品| 伊人久久精品无码av一区| 色婷婷综合久久久久中文一区二区| 久久久亚洲欧洲日产国码aⅴ|