lock語句


應用場景

lock 確保當一個線程位於代碼的臨界區時,另一個線程不進入臨界區。如果其他線程試圖進入鎖定的代碼,則它將一直等待(即被阻止),直到該對象被釋放。
lock語句根本使用的就是Monitor.EnterMonitor.Exit,也就是說lock(this)時執行Monitor.Enter(this),大括號結束時執行Monitor.Exit(this)。
應用場景:經常會應用於防止多線程操作導致公用變量值出現不確定的異常,用於確保操作的安全性,比如搶購。
鎖等於“行為可以預期”,不鎖等於“行為不可預期”。

搶購舉例

假設有商品庫存為10,共有1000名顧客在幾乎同一時間進行搶購。
不加lock的寫法:

Parallel.For(0, customerCount, (i) =>
{
	TryToBuyGoods(customerCount);
});

加lock的寫法:(實際上轉為單線程)

Parallel.For(0, customerCount, (i) =>
{
	lock (inStockLock)
	{
		TryToBuyGoods(customerCount);
	}
});

加Monitor的寫法:(實際上轉為單線程)

Parallel.For(0, customerCount, (i) =>
{
	bool lockWasTaken = false;
	try
	{
		System.Threading.Monitor.Enter(inStockLock, ref lockWasTaken);
		TryToBuyGoods(customerCount);
	}
	finally
	{
		if (lockWasTaken)
			System.Threading.Monitor.Exit(inStockLock);
	}
});
private void TryToBuyGoods(int customerCount)
{
	var buyCustomer = Customers[random.Next(0, customerCount)];
	var sleepTime = random.Next(1000, 10000);
	if (inStock > 0)
	{
		//模擬購物業務邏輯處理時間(占用資源)
		Thread.Sleep(sleepTime);
		inStock--;
		//上述流程是先處理一系列業務邏輯,后減庫存,在不加lock的情況下會出現超賣現象
		//建議的邏輯是,先減庫存-處理業務邏輯-后續庫存不足,恢復庫存,並提示用戶“購買失敗”
		Console.WriteLine($"顧客{buyCustomer.Name}購買了一件商品");
	}
	//Console.WriteLine($"當前庫存:{inStock}");
}

結果如下:



可以看出,這種情況不加lock是非常危險的事情。

示例代碼

UseLockDemo

參考資料

lock 語句(C# 參考)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM