zoukankan      html  css  js  c++  java
  • 浅谈 .Net 中 lock 与 Monitor 之锁定方法同步操作

    需求:

    最近在项目中遇到一个情况,某一个方法需要完成一个号码预占的动作,并发量也比较大。

    并且要求第一个提交抢号的人得到该号码。而后其他并发提交的人提示抢号失败。

    废话不多说,上代码。

    class Program
        {
            static void Main(string[] args)
            {
                for (int i = 0; i < 100; i++)
                {
                    Thread thread = new Thread(new ThreadStart(new Preemption().test));
                    thread.Start();
                    Thread.Sleep(300);//请求间隔
                }
            }
        }
    
        public class Preemption : Base
        {
            public void test()
            {
                base.LockTest("400-6666-8888");
            }
        }
    
        public class Base
        {
            /// <summary>
            /// 预占号码列表
            /// </summary>
            private static List<string> numberArr = new List<string>();
    
            public bool LockTest(string number)
            {
                if (numberArr.Contains(number))
                {
                    Console.WriteLine(number + "已被锁定");
                    return false;
                }
                else
                {
                    try
                    {
                        numberArr.Add(number);
    
                        Console.WriteLine("已锁定" + number);
    
                        int index = numberArr.FindIndex(t => t == number);
    
                        lock (numberArr[index])
                        {
                            Console.WriteLine(number + "正在预占...");
    
                            Thread.Sleep(3000);//模拟该方法操作为3秒
    
                            Console.WriteLine(number + "预占成功!");
                        }
                    }
                    catch (Exception)
                    {
                    }
                    finally
                    {
                        numberArr.Remove(number); //执行完成后在预占列表中清除该号码
                    }
                    return true;
                }
            }
        }
    lock版多并发预占号码

    运行的效果图如下:

         

         并发预占间隔为300毫秒一次,预占号码消耗时间为3秒一次。由以上代码改变这2个参数可得到不同的效果。

    ---------------------------------------------【Monitor版】----------------------------------------------------

    同样的需求,下面来一个Monitor版本的。

    代码如下:

    class Program
        {
            static void Main(string[] args)
            {
                for (int i = 0; i < 100; i++)
                {
                    Thread thread1 = new Thread(new ThreadStart(new Preemption().test));
                    thread1.Start();
                    Thread.Sleep(1000);//并发时间
                }
            }
        }
    
        public class Preemption : Base
        {
            public void test()
            {
                new Base().LockTest("400-6666-8888");
            }
        }
    
        public class Base
        {
            /// <summary>
            /// 预占号码列表
            /// </summary>
            private static List<string> numberArr = new List<string>();
    
            public void LockTest(string number)
            {
                if (numberArr.Contains(number))
                {
                    Console.WriteLine(number + "已被锁定");
                }
                else
                {
                    numberArr.Add(number);
    
                    int index = numberArr.FindIndex(t => t == number);
    
                    if (Monitor.TryEnter(numberArr[index], 250))//250毫秒的等待
                    {
                        try
                        {
                            Console.WriteLine("已锁定" + number);
    
                            Console.WriteLine(number + "正在预占...");
    
                            Thread.Sleep(5000);//操作时间
    
                            Console.WriteLine(number + "预占成功!");
                        }
                        finally
                        {
                            Monitor.Exit(numberArr[index]);//释放锁
    
                            numberArr.Remove(number); //执行完成后在预占列表中清除该号码
                        }
                    }
                    else
                    {
                        Console.WriteLine(number + "已被锁定");
                    }
                }
            }
        }
    Monitor版多并发预占号码

    运行效果如下:

     

    并发预占间隔为1秒一次,预占号码等待时长为250毫秒。由以上代码改变这2个参数可得到不同的效果。

     

    总结:

         以上操作总体为多用户操作并发时,根据条件在某种情况下对不同实例对象同一方法的请求,将只有第一条请求生效,其他后续并发无效。

         如果该号码正在预占,就返回失败。

         在Monitor版中加入了等待时间,更好的规避了死锁。

         且以上两种锁定的只是LockTest方法,其他方法都不会被干预。

  • 相关阅读:
    css3变换与过度
    之前做过的js练习题
    关于js中的array部分
    js复习内容
    关于js封装函数的一些东西
    html中padding和margin的区别和用法与存在的bug消除
    JS 实现百度搜索功能
    JS正则表达式的基础用法
    CSS3 动画及过渡详解
    JS的for循环小例子
  • 原文地址:https://www.cnblogs.com/PandaMars/p/3305419.html
Copyright © 2011-2022 走看看