• 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# 参考)

  • 相关阅读:
    python写的文件同步服务器
    从外部调用Django模块
    python监视线程池
    RabbitMQ手册翻译 RPC服务的例子
    python logging 模块完整使用示例
    使用内存磁盘加速linux
    About learning on the internet
    [转]伟大的程序员是怎样炼成的
    RabbitMQ手册翻译 Hello World的例子
    事半功倍:你应该知道的HTML5五大特性(转)
  • 原文地址:https://www.cnblogs.com/Lulus/p/12462234.html
Copyright © 2020-2023  润新知