需求:
最近在项目中遇到一个情况,某一个方法需要完成一个号码预占的动作,并发量也比较大。
并且要求第一个提交抢号的人得到该号码。而后其他并发提交的人提示抢号失败。
废话不多说,上代码。
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="" />