zoukankan      html  css  js  c++  java
  • 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中删除某个元素的3种方法
    研发团队开源管理工具最佳实践
    Cocos2dx游戏开发系列笔记13:一个横版拳击游戏Demo完结篇
    Sunny谈软件架构
    整理部分JS 控件 WEB前端常用的做成Jsp项目,方便今后直接用
    hdu3033I love sneakers! (分组背包,错了很多次)
    Using关键字的用法
    Android webViewj简单处理apk的下载链接
    山寨腾讯“爱消除”游戏之菜单特效
    Apache与Nginx优缺点比较
  • 原文地址:https://www.cnblogs.com/Lulus/p/12462234.html
Copyright © 2011-2022 走看看