背景描述,一个商城网站,一个订单支付方案有多个1.金额支付2.积分支付3.工资支付(分期和全额),所以一个订单的方案可能有1;有1、2,或1、2、3
状态,1.订单状态,2,支付状态==>多方案的订单有多个支付状态。
问题发现,一个订单多次支付!!!
于是分析,找解决方案。
1.DB 行锁
2.多线程控制
多线程测试参考 链接
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleThread { class Program { const string firstOrderId = "001"; const string secondOrderId = "002"; const string thirdOrderId = "003"; static void Main(string[] args) { test(LockType.LockObject); test(LockType.LockStaticObject); test(LockType.LockString); test(LockType.LockThis); } static void test(LockType lockType) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("----------------测试相同的订单-------------------"); Console.ForegroundColor = ConsoleColor.Green; OrderPay(firstOrderId, 1, lockType); OrderPay(firstOrderId, 2, lockType); OrderPay(firstOrderId, 3, lockType); Thread.Sleep(1000); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("----------------测试不同的订单-------------------"); Console.ForegroundColor = ConsoleColor.Green; OrderPay(firstOrderId, 1, lockType); OrderPay(secondOrderId, 1, lockType); OrderPay(thirdOrderId, 1, lockType); } static void OrderPay(string orderId, int threadNo, LockType lockType) { new Thread(() => new Payment(orderId, threadNo).Pay(lockType)).Start(); Thread.Sleep(100); } } public class Payment { private readonly string LockString; private readonly int ThreadNo; private readonly Object LockObj = new object(); private static readonly Object StaticLockObj = new object(); public Payment(string orderId, int threadNo) { this.LockString = orderId; this.ThreadNo = threadNo; } public void Pay(LockType lockType) { ShowMessage("等待资源"); switch (lockType) { case LockType.LockThis: lock (this) { ShowAction(); } break; case LockType.LockString: lock (LockString) { ShowAction(); } break; case LockType.LockObject: lock (LockObj) { ShowAction(); } break; case LockType.LockStaticObject: lock (StaticLockObj) { ShowAction(); } break; default: break; } ShowMessage("释放资源"); } private void ShowAction() { ShowMessage("进入锁并开始操作"); Thread.Sleep(1000); ShowMessage("完成操作,时间" + DateTime.Now); } private void ShowMessage(string message) { Console.WriteLine(string.Format("订单{0}的第{1}个线程{2}", LockString, ThreadNo, message)); } } public enum LockType { LockThis = 0, LockString = 1, LockObject = 2, LockStaticObject = 3 } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleThread2 { class Program { /// <summary> /// 订单号 /// </summary> const string firstOrderId = "d001"; const string secondOrderId = "d002"; const string thirdOrderId = "d003"; const string fourthOrderId = "d004"; const string fivthOrderId = "d005"; static void Main(string[] args) { Test(); } static void Test() { ConsoleOut.WriteWhite("----------------测试-------------------"); //相同的订单 一个一个来 OrderPay(firstOrderId, 1); OrderPay(firstOrderId, 2); OrderPay(firstOrderId, 3); OrderPay(firstOrderId, 4); //不同的订单可以同时处理 OrderPay(secondOrderId, 5); OrderPay(thirdOrderId, 6); OrderPay(fourthOrderId, 7); OrderPay(fivthOrderId, 8); } /// <summary> /// 多线程支付 /// </summary> /// <param name="orderId">订单号</param> /// <param name="threadNo">线程编号</param> static void OrderPay(string orderId, int threadNo) { new Thread((object x) => Payment.Pay(new object[] { orderId, threadNo })).Start(); } } /// <summary> /// 锁字典一个订单对映一个锁 /// </summary> public static class DicLockManage { /// <summary> /// 根据订单id得到,锁资源 /// </summary> public static Dictionary<string, object> dicLock = new Dictionary<string, object>(); /// <summary> /// 字典操作的锁 /// </summary> public static readonly object objLock = new object(); /// <summary> /// 得到订单锁 /// </summary> /// <param name="key"></param> /// <returns></returns> public static object GetKeyValue(string key) { lock (objLock) { if (dicLock.ContainsKey(key)) { return dicLock[key]; } else { dicLock.Add(key, new object()); return GetKeyValue(key); } } } } /// <summary> /// 订单支付类 /// </summary> public static class Payment { /// <summary> /// 模拟支付方法 /// </summary> /// <param name="objParams"></param> public static void Pay(object[] objParams) { object[] Params = objParams as object[]; string OrderId = Params[0].ToString(); int ThreadNo = Convert.ToInt32(Params[1]); //加锁 lock (DicLockManage.GetKeyValue(OrderId)) { ShowMessage(OrderId, ThreadNo, "等待资源"); ShowAction(OrderId, ThreadNo);//模拟支付 ShowMessage(OrderId, ThreadNo, "释放锁"); } } private static void ShowAction(string OrderId, int ThreadNo) { ShowMessage(OrderId, ThreadNo, "进入锁并开始操作"); ConsoleOut.WriteRed("线程" + ThreadNo + "处理中..."); Thread.Sleep(3000); ConsoleOut.WriteGreen("线程" + ThreadNo + "完成处理..."); ShowMessage(OrderId, ThreadNo, "完成操作,时间" + DateTime.Now); } private static void ShowMessage(string OrderId, int ThreadNo, string message) { ConsoleOut.WriteYellow(string.Format("订单{0}的第{1}个线程{2}", OrderId, ThreadNo, message)); } } /// <summary> /// 输出类,设置颜色 /// </summary> public static class ConsoleOut { public static void WriteWhite(string message) { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(message); } public static void WriteRed(string message) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(message); } public static void WriteYellow(string message) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(message); } public static void WriteGreen(string message) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(message); } } }
测试图
1.同一个订单多个线程访问,一个个处理
2.多个订单多个线程,可以一起处理,完成的时间一样
3.同时运行
如有问题,请指出。