溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

c#中l(wèi)ock的四種使用方式

發(fā)布時(shí)間:2020-06-01 15:26:55 來源:億速云 閱讀:7347 作者:鴿子 欄目:編程語(yǔ)言

  這里不考慮分布式或者多臺(tái)負(fù)載均衡的情況只考慮單臺(tái)機(jī)器,多臺(tái)服務(wù)器可以使用分布式鎖。出于線程安全的原因,很多種場(chǎng)景大家可能看代碼中看到lock的出現(xiàn),尤其是在資金類的處理環(huán)節(jié)。 但是lock(this)真的達(dá)到你的需求了嗎?下面用實(shí)例來說明

  理論常識(shí)不多說,回到業(yè)務(wù)場(chǎng)景,舉個(gè)例子我們的需求一般就是在某個(gè)訂單進(jìn)入某個(gè)安全優(yōu)先級(jí)比較高的流程時(shí)要針對(duì)這筆訂單做到線程互斥。至于原因,這里再插一個(gè)概念,大部分orm在做更新操作時(shí),實(shí)際上做的是全參數(shù)更新,所謂全參數(shù)更新,假如一個(gè)訂單表上有10個(gè)字段,我們只需要更新其中的一個(gè)金額字段,但是在傳統(tǒng)orm框架中實(shí)際上在訂單的實(shí)體類中賦值了所有字段而在更新操作中這些字段全部參與了更新,所以在高并發(fā)的場(chǎng)景下,如果有2個(gè)線程針對(duì)同一個(gè)訂單操作,并且沒有額外的保護(hù)程序(例如數(shù)據(jù)庫(kù)鎖、版本號(hào)等)那么在這種傳統(tǒng)框架下后一個(gè)線程更新可能就會(huì)覆蓋掉前一個(gè)線程的操作。因此lock的手段可以看成是一道保護(hù)墻。 那么接下來我們通過實(shí)例看一下lock4種不同方式(并非4種類別)之間的區(qū)別

  代碼很簡(jiǎn)單 在結(jié)果截圖后直接附上

   1. Lock(this)
c#中l(wèi)ock的四種使用方式
  可以看出lock(this),如果this是個(gè)普通的類非靜態(tài)非單例,那么lock(this)并不滿足我們的需求,甚至除了當(dāng)前線程并看不出有任何作用。

  2. Lock(LockString)
c#中l(wèi)ock的四種使用方式
Lock(LockString) 從結(jié)果上來看比較契合要求,對(duì)于同一筆訂單做到的線程互斥,對(duì)于不同訂單即使用到了同一個(gè)類也不干擾。不過根據(jù)大家的回復(fù)意見LockString并不適合鎖。

  3. Lock(Object)
c#中l(wèi)ock的四種使用方式

Lock(Object)和Lock(this)一樣,因?yàn)楦驹?者方式是相同的。推薦!

  4. Lock(StaticObject)
c#中l(wèi)ock的四種使用方式
 Lock(StaticObject) 實(shí)現(xiàn)了對(duì)于同一筆的訂單線程互斥,但是不符合的是對(duì)于不同筆的訂單同樣進(jìn)行了互斥。

  結(jié)論一目了然,理論的內(nèi)容不贅述。下面貼代碼
`
class Program
{
const string firstOrderId = "001";
const string secondOrderId = "002";
const string thirdOrderId = "003";

    static void Main()
    {
        test(LockType.LockThis);
        //test(LockType.LockString);
        //test(LockType.LockObject);
        //test(LockType.LockStaticObject);

        Console.ReadLine();
    }

    static void test(LockType lockType)
    {
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine("------------測(cè)試相同訂單------------");
        Console.ForegroundColor = ConsoleColor.White;
        OrderPay(firstOrderId, 1, lockType);
        OrderPay(firstOrderId, 2, lockType);
        OrderPay(firstOrderId, 3, lockType);
        Thread.Sleep(10000);

        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine("------------測(cè)試不同訂單------------");
        Console.ForegroundColor = ConsoleColor.White;
        OrderPay(firstOrderId, 1, lockType);
        OrderPay(secondOrderId, 1, lockType);
        OrderPay(thirdOrderId, 1, lockType);
    }

    static void OrderPay(string orderId, int threadNo, LockType lockType)
    {
        new Thread(() => new Payment(orderId, threadNo).Pay(lockType)).Start();

        Thread.Sleep(10);
    }
}

  

public class Payment
{
    private readonly string LockString;
    public readonly int ThreadNo;
    private readonly Object LockObj = new object();
    private static readonly Object StaticLockObj = new object();

    public Payment(string orderID, int threadNo)
    {
        LockString = orderID;
        ThreadNo = threadNo;
    }

    public void Pay(LockType lockType)
    {
        ShowMessage("等待鎖資源");
        switch (lockType)
        {
            case LockType.LockThis:
                lock (this)
                {
                    showAction();
                }
                break;
            case LockType.LockString:
                lock (LockString)
                {
                    showAction();
                }
                break;
            case LockType.LockObject:
                lock (LockObj)
                {
                    showAction();
                }
                break;
            case LockType.LockStaticObject:
                lock (StaticLockObj)
                {
                    showAction();
                }
                break;
        }
        ShowMessage("釋放鎖");
    }

    private void showAction()
    {
        ShowMessage("進(jìn)入鎖并開始操作");
        Thread.Sleep(2000);
        ShowMessage("操作完成,完成時(shí)間為" + DateTime.Now);
    }

    private void ShowMessage(string message)
    {
        Console.WriteLine(String.Format("訂單{0}的第{1}個(gè)線程 {2}", LockString, ThreadNo, message));
    }

}

public enum LockType
{
    LockThis = 0,
    LockString = 1,
    LockObject = 2,
    LockStaticObject = 3
}
`
希望對(duì)大家有幫助。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI