zoukankan      html  css  js  c++  java
  • .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.ListBoxTips.Items.Add(TipInfo);
    59 }
    60
    61
    62 }
    63 }

      源码下载

  • 相关阅读:
    HappyLeetcode45:Divide Two Integers
    HappyLeetcode44:Plus One
    HappyLeetcode43:Symmetric Tree
    HappyLeetcode42:Intersection of Two Linked Lists
    特征向量中心性(从文献中摘抄)
    二叉树(普通无规律)
    链式队列
    链式栈
    链表
    指针
  • 原文地址:https://www.cnblogs.com/luowanli/p/markeluo_MultiSysnc.html
Copyright © 2011-2022 走看看