示例#1
0
        /// <summary>
        ///
        /// </summary>
        private static void TestSeckillDemo()
        {
            //模拟线程数
            var thredNumber = 32;
            //模拟单线程请求数
            var requestNumber = 5;
            //秒杀库存数
            var stockNumber = 10;

            //秒杀成功队列key
            var key = "order1";
            //分布式锁key
            var nxKey = "order1NX";

            var csredis = new CSRedis.CSRedisClient(redisConnectionStr);

            csredis.Del(key);
            var isEnd = false;

            List <ManualResetEvent> manualEvents = new List <ManualResetEvent>();
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            for (int i = 0; i < thredNumber; i++)
            {
                ManualResetEvent mre = new ManualResetEvent(false);
                manualEvents.Add(mre);
                Param pra = new Param();
                pra.mrEvent = mre;
                pra.praData = i;

                ThreadPool.QueueUserWorkItem((object state) =>
                {
                    Param pra = (Param)state;
                    var sets  = pra.praData;

                    for (int i = 0; i < requestNumber; i++)
                    {
                        Thread.Sleep(50);

                        if (isEnd)
                        {
                            Console.WriteLine($"线程{sets} - 用户{i} 秒杀失败,抢完了。");
                            continue;
                        }

                        //设置客户端的标识,用于解锁
                        var nxSelfMarkvalue = $"thred{sets}_user{i}";
                        //加锁
                        var setnxResult = csredis.M5_LockPE(nxKey, nxSelfMarkvalue, 1000);
                        if (setnxResult)
                        {
                            var len = csredis.LLen(key);
                            //库存不足
                            if (len >= stockNumber)
                            {
                                isEnd = true;
                                stopwatch.Stop();
                                Console.WriteLine($"线程{sets} - 用户{i} 秒杀失败,抢完了。");
                            }
                            else
                            {
                                var value = $"线程{sets}-用户{i}";
                                csredis.LPush(key, value);
                                //解锁 nxSelfMarkvalue,防止误解锁
                                csredis.M5_UnLock(nxKey, nxSelfMarkvalue);
                                Console.WriteLine($"线程{sets} - 用户{i} 秒杀成功。");
                            }
                        }
                        else
                        {
                            Console.WriteLine($"线程{sets} - 用户{i} 系统繁忙,请稍后再试。 秒杀失败。");
                        }
                    }

                    pra.mrEvent.Set();
                    // Console.WriteLine($"线程{sets}已抢购完毕!");
                }, pra);
            }

            WaitHandle.WaitAll(manualEvents.ToArray());
            var lenALL = csredis.LLen(key);

            Console.WriteLine($"\r\n秒杀成功人数:{lenALL} 人,用时:{stopwatch.ElapsedMilliseconds} 毫秒.");
            Console.WriteLine($"\r\n是否超售:{(lenALL > stockNumber ? "是":"否")}");
            Console.WriteLine("\r\n秒杀成功人员名单:");
            for (int i = 0; i < stockNumber; i++)
            {
                Console.WriteLine(csredis.RPop(key));
            }
        }