课程地址: https://study.163.com/course/courseMain.htm?courseId=1004873017
本课项目地址:https://github.com/wechatdeveloper/WechatVideoCourse
课程目标:了解Senparc.Weixin SDK 缓存策略;模拟多线程访问产生的并发,使用分布式锁控制并发
Redis 安装:
-
开启Redis服务,默认端口是6379;redis-cli.exe Set Key , Get Key
-
Redis Desktop Manager: https://github.com/uglide/RedisDesktopManager
-
下载地址:https://github.com/uglide/RedisDesktopManager/releases/tag/0.8.8
-
项目引用 Senparc.Weixin.Cache.Redis
-
Web.config 配置使用缓存:
<add key="Cache_Redis_Configuration" value="localhost:6379" />
-
Global.asax 注册测试号,参考 Senparc Sample 项目配置方法
-
多线程并行,模拟并发
-
多个进程对同1个数据进行更新操作的时候,会产生并发的情况
-
控制并发的产生需要加锁,也就进程更新数据的时候加锁,更新完成后释放锁;加锁的过程中,其他需要访问数据的进行,排队等候
-
建立LockTest方法,方法中对Static类型数据进行更新操作
- 单元测试中,开启多个线程 执行LockTest()方法模拟数据并发,会发现在抢着更新数据,导致脏读
1 //Static 保存在内存中,页面观察数据变化 2 private static int _count; 3 4 public static int Count 5 { 6 get { Thread.Sleep(50); return _count; } 7 8 set 9 { 10 //线程休眠0.1秒;模拟数据更新处理的时间 11 Thread.Sleep(100); 12 _count = value; 13 } 14 } 15 16 public ContentResult LockTest() 17 { 18 var count = Count; //数据计出来 19 Count = count + 1; //数据再更新进去 20 21 string strResult = "Count:"+ count; 22 23 return Content(strResult); 24 }
- 单元测试中,开启多个线程 执行LockTest()方法模拟数据并发,会发现在抢着更新数据,导致脏读
private int totalThread = 100; //计划线程要执行次数 private int finishedThread = 0; [TestMethod] public void LockTest() { //开启多个线程 for (int i = 0; i < 100; i++) { Thread.Sleep(100);//给个线程创建时间 Thread thread = new Thread(RunSingleLockTest); thread.Start(); } while (finishedThread!= totalThread) { //等待线程执行到100次 } Console.WriteLine("线程执行完毕:"+totalThread.ToString()); } private void RunSingleLockTest() { HomeController controller = new HomeController(); ContentResult result = controller.LockTest() as ContentResult; Console.WriteLine(result.Content); finishedThread++; //记得线程执行的次数 }
执行结果:
1 public ContentResult LockTest() 2 { 3 //获取当前缓存实例 4 var strategy = CacheStrategyFactory.GetObjectCacheStrategyInstance(); 5 using (strategy.BeginCacheLock("HomeController", "LockTest")) 6 { 7 var count = Count; //数据计出来 8 Count = count + 1; //数据再更新进去 9 string strResult = "Count:" + count; 10 return Content(strResult); 11 } 12 }
在并发控制下,线程排队执行结果:数据被顺序更新