博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【C#|.NET】lock(this)其实是个坑
阅读量:5966 次
发布时间:2019-06-19

本文共 3969 字,大约阅读时间需要 13 分钟。

  这里不考虑分布式或者多台负载均衡的情况只考虑单台机器,多台服务器可以使用分布式锁。出于线程安全的原因,很多种场景大家可能看代码中看到lock的出现,尤其是在资金类的处理环节。 但是lock(this)真的达到你的需求了吗?下面用实例来说明

  理论常识不多说,回到业务场景,举个例子我们的需求一般就是在某个订单进入某个安全优先级比较高的流程时要针对这笔订单做到线程互斥。至于原因,这里再插一个概念,大部分orm在做更新操作时,实际上做的是全参数更新,所谓全参数更新,假如一个订单表上有10个字段,我们只需要更新其中的一个金额字段,但是在传统orm框架中实际上在订单的实体类中赋值了所有字段而在更新操作中这些字段全部参与了更新,所以在高并发的场景下,如果有2个线程针对同一个订单操作,并且没有额外的保护程序(例如数据库锁、版本号等)那么在这种传统框架下后一个线程更新可能就会覆盖掉前一个线程的操作。因此lock的手段可以看成是一道保护墙。 那么接下来我们通过实例看一下lock4种不同方式(并非4种类别)之间的区别

  代码很简单 在结果截图后直接附上

   1. Lock(this)

  

  可以看出lock(this),如果this是个普通的类非静态非单例,那么lock(this)并不满足我们的需求,甚至除了当前线程并看不出有任何作用。

  2. Lock(LockString)

  

   Lock(LockString) 从结果上来看比较契合要求,对于同一笔订单做到的线程互斥,对于不同订单即使用到了同一个类也不干扰。不过根据大家的回复意见LockString并不适合锁。

  3. Lock(Object)

  

  Lock(Object)和Lock(this)一样,因为根本原因2者方式是相同的。推荐!

  4. Lock(StaticObject)

  

  Lock(StaticObject) 实现了对于同一笔的订单线程互斥,但是不符合的是对于不同笔的订单同样进行了互斥。

  结论一目了然,理论的内容不赘述。下面贴代码

  

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("------------测试相同订单------------");            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("------------测试不同订单------------");            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("进入锁并开始操作");            Thread.Sleep(2000);            ShowMessage("操作完成,完成时间为" + DateTime.Now);        }        private void ShowMessage(string message)        {            Console.WriteLine(String.Format("订单{0}的第{1}个线程 {2}", LockString, ThreadNo, message));        }    }    public enum LockType    {        LockThis = 0,        LockString = 1,        LockObject = 2,        LockStaticObject = 3    }

  希望对大家有帮助。

转载地址:http://rtvax.baihongyu.com/

你可能感兴趣的文章
用a标签实现submit提交按钮的效果
查看>>
第十周
查看>>
毕向东_Java基础视频教程第20天_IO流(1~4)
查看>>
几图理解BeautifulSoup
查看>>
HashMap内部是如何实现的(转)
查看>>
交互设计[3]--点石成金
查看>>
java实现双向循环链表
查看>>
如何使用缓存提高程序性能
查看>>
【trie树】HDU4825 Xor Sum
查看>>
服务器搭建4 安装其它库
查看>>
CAD绘制栏杆5.10
查看>>
自动化学习
查看>>
JS中的!=、== 、!==、===的用法和区别。
查看>>
vs2017 增加平台集
查看>>
Kinect+OpenNI学习笔记之10(不需要骨骼跟踪的人体多个手部分割)
查看>>
spring mvc(4)处理模型数据
查看>>
JS 判断当前使用浏览器名及版本
查看>>
让所有浏览器支持HTML5 video视频标签
查看>>
Socket 详解
查看>>
[Android Pro] Java进阶学习:jar打包详解
查看>>