NET 多线程同步 / 并发操作数据唯一

在实际应用过程中很多情况下涉及大批量、频繁访问,这样就会存在并发操作,如何保证数据的唯一正确性就成了一个问题,以下将自己为别人做的一个示例展示给大家,什么不足的地方大家也提提意见!

  应用场景:

       售票系统,假如涉及到以下几种简单数据访问操作: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 }

 

  源码下载

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值