在实际应用过程中很多情况下涉及大批量、频繁访问,这样就会存在并发操作,如何保证数据的唯一正确性就成了一个问题,以下将自己为别人做的一个示例展示给大家,什么不足的地方大家也提提意见!
应用场景:
售票系统,假如涉及到以下几种简单数据访问操作:1.余票查询;2.购票;3:临时增加售票/退票 ,如果访问量较大,很多个用户同时访问时。
如1和2同时操作,2和3同时操作,1和3同时操作,就可能导致获取的数据信息不准确,这里我们就需要的效果就是当任何一个用户在进行如上的1或2或3操作时,其它用户都处于等待状态,只有前一个用户执行完后,其它用户方可进行。
不废话了,直接上代码:
1.处理类 TicketFactory(增/删/查)
此处理类即可保证查询余票、购票、退票 时,数据的唯一准确性
1 /**************************************** 模块头 *****************************************/ 2 * 模块名:TicketFactory.cs 3 * 项目名:MultiThreadSync 4 * 版权 (c) markeluo 5 * 6 * 本项目演示了在多线程并发对同一个对象进行操作,如何保证对象的唯一性 7 * 8 /*****************************************************************************************/ 9 10 using System; 11 using System.Collections.Generic; 12 using System.Linq; 13 using System.Text; 14 15 namespace MultiThreadSync 16 { 17 /// <summary> 18 /// 余票处理类(查询余票、购票、退票) 19 /// </summary> 20 public class TicketFactory 21 { 22 private static TicketFactory ticketmanager = new TicketFactory(); 23 /// <summary> 24 /// 锁定对象 25 /// </summary> 26 private static object _sysobj = new object(); 27 /// <summary> 28 /// 余票处理 实例 单例 29 /// </summary> 30 public static TicketFactory Instanc 31 { 32 get 33 { 34 return ticketmanager; 35 } 36 } 37 38 /// <summary> 39 /// 余票总数量 (假设此数据是从数据库中获取的) 40 /// </summary> 41 private int TicketCount = 10000; 42 43 /// <summary> 44 /// 查询余票 45 /// </summary> 46 /// <returns></returns> 47 public int GetTickets() 48 { 49 lock (_sysobj) 50 { 51 //暂停1秒以测试效果 52 System.Threading.Thread.Sleep(1000); 53 54 return TicketCount; 55 //实际应该从数据库中获取 56 } 57 } 58 59 /// <summary> 60 /// 退票/增加票数 61 /// </summary> 62 /// <returns></returns> 63 public void AddTickets(int Count) 64 { 65 lock (_sysobj) 66 { 67 //暂停2秒以测试效果 68 System.Threading.Thread.Sleep(2000); 69 70 TicketCount += Count; 71 //实际应该添加到数据库 72 } 73 } 74 75 /// <summary> 76 /// 购票 77 /// </summary> 78 /// <param name="Count"></param> 79 public void BuyTickets(int Count) 80 { 81 lock (_sysobj) 82 { 83 //暂停3秒以测试效果 84 System.Threading.Thread.Sleep(3000); 85 86 TicketCount -= Count; 87 //实际应该从数据库中移除相应的专利数量 88 } 89 } 90 91 } 92 }
2.多线程调用测试类
1 /**************************************** 模块头 *****************************************/ 2 * 模块名:StartMultiThread.cs 3 * 项目名:MultiThreadSync 4 * 版权 (c) markeluo 5 * 6 * 本项目演示了在多线程并发对同一个对象进行操作,如何保证对象的唯一性 7 * 8 /*****************************************************************************************/ 9 10 using System; 11 using System.Collections.Generic; 12 using System.Linq; 13 using System.Text; 14 15 namespace MultiThreadSync 16 { 17 /// <summary> 18 /// 多线程测试类 19 /// </summary> 20 public class StartMultiThread 21 { 22 public delegate void DelEventArg(string TipInfo); 23 24 /// <summary> 25 /// 余票数量处理提示 26 /// </summary> 27 public event DelEventArg TickedCountChangeEvent; 28 29 public void Start() 30 { 31 //线程1 32 System.Threading.Thread Thread1 = new System.Threading.Thread(new System.Threading.ThreadStart(TicketManager1)); 33 Thread1.IsBackground = true; 34 Thread1.Start(); 35 36 //线程2 37 System.Threading.Thread Thread2 = new System.Threading.Thread(new System.Threading.ThreadStart(TicketManager2)); 38 Thread2.IsBackground = true; 39 Thread2.Start(); 40 41 //线程3 42 System.Threading.Thread Thread3 = new System.Threading.Thread(new System.Threading.ThreadStart(TicketManager3)); 43 Thread3.IsBackground = true; 44 Thread3.Start(); 45 46 //线程4 47 System.Threading.Thread Thread4 = new System.Threading.Thread(new System.Threading.ThreadStart(TicketManager4)); 48 Thread4.IsBackground = true; 49 Thread4.Start(); 50 51 } 52 53 /// <summary> 54 /// 余票处理1 55 /// </summary> 56 private void TicketManager1() 57 { 58 DateTime _startTime = DateTime.Now; 59 TicketFactory.Instanc.AddTickets(2); 60 if (TickedCountChangeEvent != null) 61 { 62 string strTip = string.Format("线程1 {0}-{1} 退票2张!", _startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); 63 TickedCountChangeEvent(strTip); 64 } 65 66 _startTime = DateTime.Now; 67 TicketFactory.Instanc.BuyTickets(1); 68 if (TickedCountChangeEvent != null) 69 { 70 string strTip = string.Format("线程1 {0}-{1} 购票1张!", _startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); 71 TickedCountChangeEvent(strTip); 72 } 73 74 _startTime = DateTime.Now; 75 int _Count = TicketFactory.Instanc.GetTickets(); 76 if (TickedCountChangeEvent != null) 77 { 78 string strTip = string.Format("线程1 {0}-{1} 查询余票,还剩{2}张!", _startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), _Count); 79 TickedCountChangeEvent(strTip); 80 } 81 } 82 83 /// <summary> 84 /// 余票处理2 85 /// </summary> 86 private void TicketManager2() 87 { 88 DateTime _startTime = DateTime.Now; 89 TicketFactory.Instanc.AddTickets(2); 90 if (TickedCountChangeEvent != null) 91 { 92 string strTip = string.Format("线程2 {0}-{1} 退票2张!", _startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); 93 TickedCountChangeEvent(strTip); 94 } 95 96 _startTime = DateTime.Now; 97 TicketFactory.Instanc.BuyTickets(1); 98 if (TickedCountChangeEvent != null) 99 { 100 string strTip = string.Format("线程2 {0}-{1} 购票1张!", _startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); 101 TickedCountChangeEvent(strTip); 102 } 103 104 _startTime = DateTime.Now; 105 int _Count = TicketFactory.Instanc.GetTickets(); 106 if (TickedCountChangeEvent != null) 107 { 108 string strTip = string.Format("线程2 {0}-{1} 查询余票,还剩{2}张!", _startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), _Count); 109 TickedCountChangeEvent(strTip); 110 } 111 } 112 113 /// <summary> 114 /// 余票处理3 115 /// </summary> 116 private void TicketManager3() 117 { 118 DateTime _startTime = DateTime.Now; 119 TicketFactory.Instanc.AddTickets(2); 120 if (TickedCountChangeEvent != null) 121 { 122 string strTip = string.Format("线程3 {0}-{1} 退票2张!", _startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); 123 TickedCountChangeEvent(strTip); 124 } 125 126 _startTime = DateTime.Now; 127 TicketFactory.Instanc.BuyTickets(1); 128 if (TickedCountChangeEvent != null) 129 { 130 string strTip = string.Format("线程3 {0}-{1} 购票1张!", _startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); 131 TickedCountChangeEvent(strTip); 132 } 133 134 _startTime = DateTime.Now; 135 int _Count = TicketFactory.Instanc.GetTickets(); 136 if (TickedCountChangeEvent != null) 137 { 138 string strTip = string.Format("线程3 {0}-{1} 查询余票,还剩{2}张!", _startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), _Count); 139 TickedCountChangeEvent(strTip); 140 } 141 } 142 143 /// <summary> 144 /// 余票处理4 145 /// </summary> 146 private void TicketManager4() 147 { 148 DateTime _startTime = DateTime.Now; 149 TicketFactory.Instanc.AddTickets(2); 150 if (TickedCountChangeEvent != null) 151 { 152 string strTip = string.Format("线程4 {0}-{1} 退票2张!", _startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); 153 TickedCountChangeEvent(strTip); 154 } 155 156 _startTime = DateTime.Now; 157 TicketFactory.Instanc.BuyTickets(1); 158 if (TickedCountChangeEvent != null) 159 { 160 string strTip = string.Format("线程4 {0}-{1} 购票1张!", _startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")); 161 TickedCountChangeEvent(strTip); 162 } 163 164 _startTime = DateTime.Now; 165 int _Count = TicketFactory.Instanc.GetTickets(); 166 if (TickedCountChangeEvent != null) 167 { 168 string strTip = string.Format("线程4 {0}-{1} 查询余票,还剩{2}张!", _startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), _Count); 169 TickedCountChangeEvent(strTip); 170 } 171 } 172 173 } 174 }
3.界面显示
1 /**************************************** 模块头 *****************************************/ 2 * 模块名:Form1.cs 3 * 项目名:MultiThreadSync 4 * 版权 (c) markeluo 5 * 6 * 本项目演示了在多线程并发对同一个对象进行操作,如何保证对象的唯一性 7 * 8 /*****************************************************************************************/ 9 10 using System; 11 using System.Collections.Generic; 12 using System.ComponentModel; 13 using System.Data; 14 using System.Drawing; 15 using System.Linq; 16 using System.Text; 17 using System.Windows.Forms; 18 19 namespace MultiThreadSync 20 { 21 public partial class Form1 : Form 22 { 23 public Form1() 24 { 25 InitializeComponent(); 26 } 27 28 private void button1_Click(object sender, EventArgs e) 29 { 30 StartMultiThread _start = new StartMultiThread(); 31 _start.TickedCountChangeEvent += new StartMultiThread.DelEventArg(_start_TickedCountChangeEvent); 32 _start.Start(); 33 } 34 35 36 /// <summary> 37 /// 事件订阅处理 38 /// </summary> 39 /// <param name="TipInfo"></param> 40 void _start_TickedCountChangeEvent(string TipInfo) 41 { 42 if (this.InvokeRequired) 43 { 44 this.BeginInvoke(new StartMultiThread.DelEventArg(ShowTipInfo), new object[] { TipInfo}); 45 } 46 else 47 { 48 ShowTipInfo(TipInfo); 49 } 50 } 51 52 /// <summary> 53 /// 显示多线程访问TicketFactory ,进行增删改查的时间和顺序 54 /// </summary> 55 /// <param name="TipInfo"></param> 56 private void ShowTipInfo(string TipInfo) 57 { 58 this.ListBoxTiphotoshop/ target=_blank class=infotextkey>ps.Items.Add(TipInfo); 59 } 60 61 62 } 63 }
源码下载