当前位置: 移动技术网 > IT编程>开发语言>.net > C# 针对特定的条件进行锁操作,不用lock,而是mutex

C# 针对特定的条件进行锁操作,不用lock,而是mutex

2019年07月23日  | 移动技术网IT编程  | 我要评论

妖精国骑士,张一一的流水修真生活,江伊涵moko

背景:用户领取优惠券,同一个用户需要加锁验证是否已经领取,不同用户则可以同时领取。

上代码示例:

1、创建person类

    /// <summary>
    /// person类
    /// </summary>
    public class person
    {
        /// <summary>
        /// id
        /// </summary>
        public int id { get; set; }

        /// <summary>
        ///  姓名
        /// </summary>
        public string name { get; set; }

        /// <summary>
        /// 是否获得优惠券
        /// </summary>
        public bool isgetcoupon { get; set; }
    }

2.1、不加锁的方法(可能会出现重复领取的情况)

        /// <summary>
        /// 获取优惠券
        /// </summary>
        public static void getcoupon(person person)
        {
            console.writeline("date:{0:yyyy-mm-dd hh:mm:ss},name:{1},前来领取优惠券", datetime.now, person.name);
            if (person.isgetcoupon)
            {
                //假装业务处理
                thread.sleep(1000);
                console.writeline("date:{0:yyyy-mm-dd hh:mm:ss},name:{1},已经领取,不可重复领取", datetime.now, person.name);
            }
            else
            {
                //假装业务处理
                thread.sleep(1000);
                //领取
                person.isgetcoupon = true;
                console.writeline("date:{0:yyyy-mm-dd hh:mm:ss},name:{1},领取成功", datetime.now, person.name);
            }
        }

2.2、加lock锁的方法,所有来领优惠券的人,都得排对领(也不好)

        /// <summary>
        /// lock获取优惠券
        /// </summary>
        public static void lockgetcoupon(person person)
        {
            console.writeline("date:{0:yyyy-mm-dd hh:mm:ss},name:{1},前来领取优惠券", datetime.now, person.name);
            lock (lockobj)
            {
                //判断是否已经领取
                if (person.isgetcoupon)
                {
                    //假装业务处理
                    thread.sleep(1000);
                    console.writeline("date:{0:yyyy-mm-dd hh:mm:ss},name:{1},已经领取,不可重复领取", datetime.now, person.name);
                }
                else
                {
                    //假装业务处理
                    thread.sleep(1000);
                    //领取
                    person.isgetcoupon = true;
                    console.writeline("date:{0:yyyy-mm-dd hh:mm:ss},name:{1},领取成功", datetime.now, person.name);
                }
            }
        }

2.3、mutex锁,互斥锁,只有相同id的人,才会排对领取,不同id的人就可以同时领取

        /// <summary>
        /// mutex,领取
        /// </summary>
        /// <param name="person"></param>
        public static void mutexgetcoupon(person person)
        {
            console.writeline("date:{0:yyyy-mm-dd hh:mm:ss},name:{1},前来领取优惠券", datetime.now, person.name);
            using (var mutex = new mutex(false, person.id.tostring()))
            {
                try
                {
                    if (mutex.waitone(-1, false))
                    {
                        //判断是否已经领取
                        if (person.isgetcoupon)
                        {
                            //假装业务处理
                            thread.sleep(1000);
                            console.writeline("date:{0:yyyy-mm-dd hh:mm:ss},name:{1},已经领取,不可重复领取", datetime.now, person.name);
                        }
                        else
                        {

                            //假装业务处理
                            thread.sleep(1000);
                            //领取
                            person.isgetcoupon = true;
                            console.writeline("date:{0:yyyy-mm-dd hh:mm:ss},name:{1},领取成功", datetime.now, person.name);
                        }
                    }
                }
                catch (exception ex)
                {
                    //txtloghelper.writelog(ex);
                }
                finally
                {
                    mutex.releasemutex();
                }
            }
        }
    }

3.1、开始测试(不加锁)

        static void main(string[] args)
        {
            //实例化三个人
            person p1 = new person { id = 24, name = "kobe" };
            person p2 = new person { id = 25, name = "rose" };
            person p3 = new person { id = 23, name = "lebl" };

            //开启多线程、模拟三个人同时发起多次领取请求
            for (int i = 0; i < 4; i++)
            {
                new thread(() =>
                {
                    getcoupon(p1);
                }).start();
                new thread(() =>
                {
                    getcoupon(p2);
                }).start();
                new thread(() =>
                {
                    getcoupon(p3);
                }).start();
            }
            console.readline();
        }

测试结果:每个人都重复领取

3.2、测试lock锁方法,

        private static readonly object lockobj = new object();
        static void main(string[] args)
        {
            //实例化三个人
            person p1 = new person { id = 24, name = "kobe" };
            person p2 = new person { id = 25, name = "rose" };
            person p3 = new person { id = 23, name = "lebl" };

            //开启多线程、模拟三个人同时发起多次领取请求
            for (int i = 0; i < 4; i++)
            {
                new thread(() =>
                {
                    lockgetcoupon(p1);
                }).start();
                new thread(() =>
                {
                    lockgetcoupon(p2);
                }).start();
                new thread(() =>
                {
                    lockgetcoupon(p3);
                }).start();
            }
            console.readline();
        }

测试结果:虽然避免了重复领取,但是每个人都的每个请求都要排对。如果用户量大的话,这种方式效率就太低了,所以不推荐。

 3.3、测试mutex锁,互斥锁

        static void main(string[] args)
        {
            //实例化三个人
            person p1 = new person { id = 24, name = "kobe" };
            person p2 = new person { id = 25, name = "rose" };
            person p3 = new person { id = 23, name = "lebl" };

            //开启多线程、模拟三个人同时发起多次领取请求
            for (int i = 0; i < 4; i++)
            {
                new thread(() =>
                {
                    mutexgetcoupon(p1);
                }).start();
                new thread(() =>
                {
                    mutexgetcoupon(p2);
                }).start();
                new thread(() =>
                {
                    mutexgetcoupon(p3);
                }).start();
            }
            console.readline();
        }

测试结果:既避免了重复领取,也避免了堵塞用户请求的情况。见下面截图,kobe、rose、lebl是同时领取的优惠券,但是每个人的重复请求都在排对

总结:mutex锁,完美的解决了此类问题。

 --------------------------------------------华丽的分割线 --------------------------------------------

感谢各位大佬提出的问题和建议,我确实没有考虑到这些问题。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网