麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

細說.NET中的多線程(四使用鎖進行同步)

2019-11-14 13:50:52
字體:
來源:轉載
供稿:網友

通過鎖來實現同步

排它鎖主要用來保證,在一段時間內,只有一個線程可以訪問某一段代碼。兩種主要類型的排它鎖是lock和Mutex。Lock和Mutex相比構造起來更方便,運行的也更快。但是Mutex可以在同一個機器上的不同進程使用。

Monitor.Enter和Monitor.Exit

C#中的lock關鍵字,實際上是Monitor.Enter,Monitor.Exist的一個簡寫。在.NET 1.0,2.0,3.0 版本的c#中,lock會被編譯成如下代碼:

        Monitor.Enter(_locker);        try        {            if (_val2 != 0) Console.WriteLine(_val1 / _val2);            _val2 = 0;        }        finally { Monitor.Exit(_locker); }

如果你沒有調用Monitor.Enter而直接調用Monitor.Exit會引發異常。

LockTaken版本:

想象一下上面這段代碼,如果再Monitor.Enter之后,try之前,線程出現了異常(比如被終止),在這種情況下,finally中的Exit方法就永遠不會被執行,也就導致了這個鎖不會被釋放。為了避免這種情況,CLR 4.0的設計者重載了Monitor.Enter方法:

public static void Enter (object obj, ref bool lockTaken);

 

如果當前線程由于某些異常導致鎖沒有被獲取到,lockTake值會為false,因此在CLR 4.0中,lock會被解釋成如下代碼:

        bool lockTaken = false;        try        {            Monitor.Enter(_locker, ref lockTaken);            // Do your stuff...        }        finally { if (lockTaken) Monitor.Exit(_locker); }

TryEnter

Monitor也提供了了一個TryEnter方法,允許你設置一個超時時間,避免當前線程長時間獲取不到鎖而一直等待。

選擇正確的同步對象

你需要選擇一個對所有線程都可見的對象進行lock(obj)來確保程序能夠按照你的意圖執行。如果比不了解C#語言中的某些特性,lock可能不會按照你 期望來執行。

  1. 由于字符串的駐留機制,lock("string")不是一個好的選擇
  2. Lock一個值類型不是一個好的選擇
  3. Lock(typeof(..))不是一個好的選擇,因為System.Type的特性

什么時候使用lock

一個基本的規則,你需要對任意的寫操作,或者可修改的字段進行lock。即使是一個賦值操作,或者累加操作,你也不能假設他是線程安全的。

例如下面代碼不是線程安全的:

        class ThreadUnsafe        {            static int _x;            static void Increment() { _x++; }            static void Assign() { _x = 123; }        }

 

你需要這樣寫:

        class ThreadSafe        {            static readonly object _locker = new object();            static int _x;            static void Increment() { lock (_locker) _x++; }            static void Assign() { lock (_locker) _x = 123; }        }

如果你看過一些BCL類庫里面的實現,你可以能會發現,某些情況下會使用InterLocked類,而不是lock,我們會在后面介紹。

關于嵌套鎖或者reentrant

你在閱讀一些文檔的時候,有的文檔可能會說lock或者Monitor.Enter是reentrant(可重入的),那么我們如何理解reentrant呢?

想象下以下代碼:

            lock (locker)                lock (locker)                    lock (locker)                    {                        // Do something...                    }

 

或者是:

            Monitor.Enter(locker); Monitor.Enter(locker); Monitor.Enter(locker);            // Do something...            Monitor.Exit(locker); Monitor.Exit(locker); Monitor.Exit(locker);

這種情況下,只有在最后一個exit執行后,或者執行了相應次數的Exit后,locker才是可獲取的狀態。

Mutex

Mutex像c#中的lock一樣,但是在不同的進程中仍然可以使用。換句話說,Mutex是一個計算機級別的鎖。因此獲取這樣一個鎖要比Monitor慢很多。

示例代碼:

 

using System;using System.Threading.Tasks;using System.Threading;namespace MultiThreadTest{    class OneAtATimePlease    {        static void Main()        {            // Naming a Mutex makes it available computer-wide. Use a name that's            // unique to your company and application (e.g., include your URL).            using (var mutex = new Mutex(false, "oreilly.com OneAtATimeDemo"))            {                // Wait a few seconds if contended, in case another instance                // of the PRogram is still in the process of shutting down.                if (!mutex.WaitOne(TimeSpan.FromSeconds(3), false))                {                    Console.WriteLine("Another app instance is running. Bye!");                    return;                }                RunProgram();            }        }        static void RunProgram()        {            Console.WriteLine("Running. Press Enter to exit");            Console.ReadLine();        }    }}

Semaphore

Monitor和Mutex都是排他鎖,Semaphore我們常用的另外一種非排他的鎖。

我們用它來實現這樣一個例子:一個酒吧,最多能容納3人,如果客滿則需要等待,有客人離開,等待的人隨時可以進來。

示例代碼:

using System;using System.Threading;class TheClub      // No door lists!{    static Semaphore _sem = new Semaphore(3, 3);    // Capacity of 3    static void Main()    {        for (int i = 1; i <= 5; i++) new Thread(Enter).Start(i);        Console.ReadLine();    }    static void Enter(object id)    {        Console.WriteLine(id + " wants to enter");        _sem.WaitOne();        Console.WriteLine(id + " is in!");           // Only three threads        Thread.Sleep(1000 * (int)id);               // can be here at        Console.WriteLine(id + " is leaving");       // a time.        _sem.Release();    }}

 

使用Semaphore需要調用者來控制訪問資源,調用WaitOne來獲取資源,通過Release來釋放資源。開發者有責任確保資源能夠正確釋放。

Semaphore在限制同步訪問的時候非常有用,它不會像Monitor或者Mutex那樣當一個線程訪問某些資源時,其它所有線程都需要等,而是設置一個緩沖區,允許最多多少個線程同時進行訪問。

Semaphore也可以像Mutex一樣,跨進程進行同步。

 

本節主要總結了使用鎖進行同步,下一節將總結使用信號量進行同步。      


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 91成人免费看片 | www.99热精品 | 欧美综合成人 | 精品国产一区二区在线观看 | 午夜精品福利视频 | 在线小视频国产 | 国产88久久久国产精品免费二区 | 国产乱色精品成人免费视频 | 91免费视频版 | 欧美亚洲国产一区二区三区 | 亚洲国产一区二区三区 | 一本精品999爽爽久久久 | 91一区二区在线观看 | 亚洲一区国产二区 | 福利免费观看 | 久久超碰99 | 中文在线观看www | 天天干天天透 | 欧美一极视频 | 热99re久久免费视精品频软件 | 国产乱子视频 | 欧美 亚洲 激情 | 日韩黄色三级视频 | 麻豆porn| 宅男噜噜噜66一区二区 | 国产午夜电影在线观看 | h网站在线观看 | 欧美日韩国产中文字幕 | 草莓福利视频在线观看 | 日本高清com | www.guochanav.com | 精品国产一区二 | 爽爽淫人综合网网站 | 视频一区二区三区免费观看 | 亚洲综人网 | 成人毛片视频在线播放 | 国产精品成人久久久久a级 欧美特黄一级高清免费的香蕉 | 斗破苍穹在线观看免费完整观看 | 成人羞羞国产免费游戏 | 国产精品成人av片免费看最爱 | 最新91在线视频 |