浅谈 .Net 中 lock 与 Monitor 之锁定方法同步操作_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 浅谈 .Net 中 lock 与 Monitor 之锁定方法同步操作

浅谈 .Net 中 lock 与 Monitor 之锁定方法同步操作

 2013/9/7 21:12:36  待风将我埋葬  博客园  我要评论(0)
  • 摘要:需求:最近在项目中遇到一个情况,某一个方法需要完成一个号码预占的动作,并发量也比较大。并且要求第一个提交抢号的人得到该号码。而后其他并发提交的人提示抢号失败。废话不多说,上代码。classProgram{staticvoidMain(string[]args){for(inti=0;i<100;i++){Threadthread=newThread(newThreadStart(newPreemption().test));thread.Start();Thread.Sleep(300)
  • 标签:.net 方法 net 浅谈 操作 同步

需求:

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

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

废话不多说,上代码。

class="code_img_closed" src="/Upload/Images/2013090721/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('6adfd094-94ed-40b2-8c00-7255433cb376',event)" src="/Upload/Images/2013090721/2B1B950FA3DF188F.gif" alt="" />
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方法,其他方法都不会被干预。

Tencent\Users\253463947\QQ\WinTemp\RichOle\Z28(DJL{JHTS(DD0)2Q%5GX.jpg" alt="" />
发表评论
用户名: 匿名