在实际应用过程中很多情况下涉及大批量、频繁访问,这样就会存在并发操作,如何保证数据的唯一正确性就成了一个问题,以下将自己为别人做的一个示例展示给大家,什么不足的地方大家也提提意见!
应用场景:
售票系统,假如涉及到以下几种简单数据访问操作: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.ListBoxTips.Items.Add(TipInfo);
59 }
60
61
62 }
63 }