.NET 多线程同步 / 并发操作数据唯一
2012-02-26 13:33
369 查看
在实际应用过程中很多情况下涉及大批量、频繁访问,这样就会存在并发操作,如何保证数据的唯一正确性就成了一个问题,以下将自己为别人做的一个示例展示给大家,什么不足的地方大家也提提意见!
应用场景:
售票系统,假如涉及到以下几种简单数据访问操作:1.余票查询;2.购票;3:临时增加售票/退票 ,如果访问量较大,很多个用户同时访问时。
如1和2同时操作,2和3同时操作,1和3同时操作,就可能导致获取的数据信息不准确,这里我们就需要的效果就是当任何一个用户在进行如上的1或2或3操作时,其它用户都处于等待状态,只有前一个用户执行完后,其它用户方可进行。
不废话了,直接上代码:
1.处理类 TicketFactory(增/删/查)
此处理类即可保证查询余票、购票、退票 时,数据的唯一准确性
2.多线程调用测试类
3.界面显示
源码下载
应用场景:
售票系统,假如涉及到以下几种简单数据访问操作:1.余票查询;2.购票;3:临时增加售票/退票 ,如果访问量较大,很多个用户同时访问时。
如1和2同时操作,2和3同时操作,1和3同时操作,就可能导致获取的数据信息不准确,这里我们就需要的效果就是当任何一个用户在进行如上的1或2或3操作时,其它用户都处于等待状态,只有前一个用户执行完后,其它用户方可进行。
不废话了,直接上代码:
1.处理类 TicketFactory(增/删/查)
此处理类即可保证查询余票、购票、退票 时,数据的唯一准确性
/**************************************** 模块头 *****************************************\ * 模块名:TicketFactory.cs * 项目名:MultiThreadSync * 版权 (c) markeluo * * 本项目演示了在多线程并发对同一个对象进行操作,如何保证对象的唯一性 * \*****************************************************************************************/ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MultiThreadSync { /// <summary> /// 余票处理类(查询余票、购票、退票) /// </summary> public class TicketFactory { private static TicketFactory ticketmanager = new TicketFactory(); /// <summary> /// 锁定对象 /// </summary> private static object _sysobj = new object(); /// <summary> /// 余票处理 实例 单例 /// </summary> public static TicketFactory Instanc { get { return ticketmanager; } } /// <summary> /// 余票总数量 (假设此数据是从数据库中获取的) /// </summary> private int TicketCount = 10000; /// <summary> /// 查询余票 /// </summary> /// <returns></returns> public int GetTickets() { lock (_sysobj) { //暂停1秒以测试效果 System.Threading.Thread.Sleep(1000); return TicketCount; //实际应该从数据库中获取 } } /// <summary> /// 退票/增加票数 /// </summary> /// <returns></returns> public void AddTickets(int Count) { lock (_sysobj) { //暂停2秒以测试效果 System.Threading.Thread.Sleep(2000); TicketCount += Count; //实际应该添加到数据库 } } /// <summary> /// 购票 /// </summary> /// <param name="Count"></param> public void BuyTickets(int Count) { lock (_sysobj) { //暂停3秒以测试效果 System.Threading.Thread.Sleep(3000); TicketCount -= Count; //实际应该从数据库中移除相应的专利数量 } } } }
2.多线程调用测试类
/**************************************** 模块头 *****************************************\ * 模块名:StartMultiThread.cs * 项目名:MultiThreadSync * 版权 (c) markeluo * * 本项目演示了在多线程并发对同一个对象进行操作,如何保证对象的唯一性 * \*****************************************************************************************/ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MultiThreadSync { /// <summary> /// 多线程测试类 /// </summary> public class StartMultiThread { public delegate void DelEventArg(string TipInfo); /// <summary> /// 余票数量处理提示 /// </summary> public event DelEventArg TickedCountChangeEvent; public void Start() { //线程1 System.Threading.Thread Thread1 = new System.Threading.Thread(new System.Threading.ThreadStart(TicketManager1)); Thread1.IsBackground = true; Thread1.Start(); //线程2 System.Threading.Thread Thread2 = new System.Threading.Thread(new System.Threading.ThreadStart(TicketManager2)); Thread2.IsBackground = true; Thread2.Start(); //线程3 System.Threading.Thread Thread3 = new System.Threading.Thread(new System.Threading.ThreadStart(TicketManager3)); Thread3.IsBackground = true; Thread3.Start(); //线程4 System.Threading.Thread Thread4 = new System.Threading.Thread(new System.Threading.ThreadStart(TicketManager4)); Thread4.IsBackground = true; Thread4.Start(); } /// <summary> /// 余票处理1 /// </summary> private void TicketManager1() { DateTime _startTime = DateTime.Now; TicketFactory.Instanc.AddTickets(2); if (TickedCountChangeEvent != null) { 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")); TickedCountChangeEvent(strTip); } _startTime = DateTime.Now; TicketFactory.Instanc.BuyTickets(1); if (TickedCountChangeEvent != null) { 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")); TickedCountChangeEvent(strTip); } _startTime = DateTime.Now; int _Count = TicketFactory.Instanc.GetTickets(); if (TickedCountChangeEvent != null) { 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); TickedCountChangeEvent(strTip); } } /// <summary> /// 余票处理2 /// </summary> private void TicketManager2() { DateTime _startTime = DateTime.Now; TicketFactory.Instanc.AddTickets(2); if (TickedCountChangeEvent != null) { 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")); TickedCountChangeEvent(strTip); } _startTime = DateTime.Now; TicketFactory.Instanc.BuyTickets(1); if (TickedCountChangeEvent != null) { 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")); TickedCountChangeEvent(strTip); } _startTime = DateTime.Now; int _Count = TicketFactory.Instanc.GetTickets(); if (TickedCountChangeEvent != null) { 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); TickedCountChangeEvent(strTip); } } /// <summary> /// 余票处理3 /// </summary> private void TicketManager3() { DateTime _startTime = DateTime.Now; TicketFactory.Instanc.AddTickets(2); if (TickedCountChangeEvent != null) { 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")); TickedCountChangeEvent(strTip); } _startTime = DateTime.Now; TicketFactory.Instanc.BuyTickets(1); if (TickedCountChangeEvent != null) { 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")); TickedCountChangeEvent(strTip); } _startTime = DateTime.Now; int _Count = TicketFactory.Instanc.GetTickets(); if (TickedCountChangeEvent != null) { 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); TickedCountChangeEvent(strTip); } } /// <summary> /// 余票处理4 /// </summary> private void TicketManager4() { DateTime _startTime = DateTime.Now; TicketFactory.Instanc.AddTickets(2); if (TickedCountChangeEvent != null) { 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")); TickedCountChangeEvent(strTip); } _startTime = DateTime.Now; TicketFactory.Instanc.BuyTickets(1); if (TickedCountChangeEvent != null) { 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")); TickedCountChangeEvent(strTip); } _startTime = DateTime.Now; int _Count = TicketFactory.Instanc.GetTickets(); if (TickedCountChangeEvent != null) { 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); TickedCountChangeEvent(strTip); } } } }
3.界面显示
/**************************************** 模块头 *****************************************\ * 模块名:Form1.cs * 项目名:MultiThreadSync * 版权 (c) markeluo * * 本项目演示了在多线程并发对同一个对象进行操作,如何保证对象的唯一性 * \*****************************************************************************************/ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace MultiThreadSync { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { StartMultiThread _start = new StartMultiThread(); _start.TickedCountChangeEvent += new StartMultiThread.DelEventArg(_start_TickedCountChangeEvent); _start.Start(); } /// <summary> /// 事件订阅处理 /// </summary> /// <param name="TipInfo"></param> void _start_TickedCountChangeEvent(string TipInfo) { if (this.InvokeRequired) { this.BeginInvoke(new StartMultiThread.DelEventArg(ShowTipInfo), new object[] { TipInfo}); } else { ShowTipInfo(TipInfo); } } /// <summary> /// 显示多线程访问TicketFactory ,进行增删改查的时间和顺序 /// </summary> /// <param name="TipInfo"></param> private void ShowTipInfo(string TipInfo) { this.ListBoxTips.Items.Add(TipInfo); } } }
源码下载
相关文章推荐
- .NET 多线程同步 / 并发操作数据唯一
- NET 多线程同步 / 并发操作数据唯一
- 真实世界的 XML:使用 .NET 框架中集成的读取器和写入器很容易操作 XML 数据
- 如何处理大量数据高并发大流量并发操作方案
- 数据库的并发操作与数据的不一致性
- ASP.NET 2.0中操作数据:实现开放式并发
- .net 数据结构与算法基础:图的操作
- .net 互操作之p/invoke- 数据封送(嵌套结构体,类,数组)(5)
- Flex与.NET互操作(二):基于WebService的数据访问(上)
- 并发 防止 重复提交唯一数据
- Flex与.NET互操作(四):使用HttpService、URLReqeust和URLLoader加载/传输数据
- .net中利用oracle产品自带的数据访问组件(Oracle.DataAccess.dll)提升批量更新操作的执行效率
- 如何处理大量数据并发操作
- 高并发操作和查询的数据采集和查询系统的oracle数据库设计建议
- .net 互操作之p/invoke- 数据封送(字符串版本-ANSI和UniCode,返回错误码,回调函数,常量)(6)
- Flex与.NET互操作(三):基于WebService的数据访问(下)
- 并发操作会带来数据的不一致性
- 如何处理大量数据并发操作(数据库锁机制详解)
- .net 如何处理并发操作
- 在ASP.NET 2.0中操作数据之二十一:实现开放式并发