zoukankan      html  css  js  c++  java
  • .net core WebApi Monitor实现并发同步

    在.net中,还可以使用Monitor实现线程并发同步。Monitor类是纯托管且完全可移植,并且可能会在操作系统资源需求方面更加高效。

    Monitor的锁对象尽可能使用引用对象,如果是字符串或值对象,会出现引发SynchronizationLockException异常。

    其实我们日常用的lock锁同步,其原理就是基于Monitor的。

    即:

    public static readonly object locker=new object();
    lock(locker){
        //to do something
    }

    和以下代码是一样的意思:

    public static readonly object locker=new object();
    try{
        Monitor.Enter(locker);
    
        //to do something
    }finally{
        Monitor.Exit(locker);
    }

    以下是基于测试的代码:

            protected static readonly object _locker = new object();
    [HttpGet(
    "[controller]/api/[action]")] public IActionResult Test() { int threadId = Thread.CurrentThread.ManagedThreadId; ResponseModel rc = new ResponseModel(0, $"{threadId} 初始化"); try { //独占资源锁 Monitor.Enter(_locker); int count = RedisHelper.GetAsync(RTestKey).Result.ToInt32(); if (count > 0) { if (RedisHelper.SetAsync(RTestKey, "-1").Result) rc.SetMessage($"{threadId} 设置成功!"); } else rc.SetMessage($"{threadId} 已被设置,不能再次设置!"); } catch (Exception ex) { _log.Error(ex); } finally { //释放锁,让其他线程获取锁并进入该方法 Monitor.Exit(_locker); } return Json(rc); }

    接下来通过测试程序连续发送8次请求,看看结果:

    通过以上操作,证明可以使用Monitor实现多线程的并发同步操作。

    如果在执行了Monitor.Enter(locker)之后,需要释放锁对象并阻塞当前线程,让其他线程获取锁并执行的话,可以使用Monitor.Wait()方法。Monitor.Wait()方法的作用就是释放当前线程持有的锁,让当前线程进入等待队列,让其他某个线程获取锁对象并进入就绪状态并执行。其他线程执行Monitor.Pulse或PulseAll方法之后,当前等待的线程就可以继续获取锁并进入就绪队列去执行。

    Monitor的Wait、Pulse和PulseAll方法必须在Enter和Exit方法之间调用。

    如下测试代码:

            static void Func1() {
                Monitor.Enter(_locker);
                for(int i = 1; i < 5; i++)
                {                
                    Console.Write($"=>Func1【{i}】");
                    Monitor.Pulse(_locker);
                    Monitor.Wait(_locker);
                }           
                
                Monitor.Exit(_locker);
            }
    
            static void Func2()
            {
                Monitor.Enter(_locker);
                for (int i = 1; i < 5; i++)
                {
                    Monitor.Wait(_locker);
                    Console.Write($"=>Func2【{i}】");
                    Monitor.Pulse(_locker);               
                }
    
                Monitor.Exit(_locker);
            }     
    
            static void Func4() {
                List<Task> list = new List<Task>{
                    Task.Factory.StartNew(Func1),
                    Task.Factory.StartNew(Func2)                
                };
    
                Task.WaitAll(list.ToArray());
            }
    
            public static readonly object _locker = new object();
            static void Main(string[] args)
            {
                Func4();
            }

    这段代码的目的是Fun1函数执行一次后,Fun2函数再执行一次,依次循环。让我们看看执行的结果:

    由此看来,达到了本次测试的目的。

  • 相关阅读:
    【一句日历】2020年4月
    【2020-03-31】思维永远只有一种
    【2020-03-30】事情就怕太容易而看不起
    【2020-03-29】人生有趣的地方在于不断升级自己
    【2020-03-27】球场还在,换了地方而已
    【2020-03-26】人其实是一个系统
    【2020-03-25】没工作是个伪命题
    day 74 vue 2 axios数据请求 以及组件的学习
    day 73 初学vue (1)
    day 72 crm(9) 客户关系系统,整体实现,以及自定制路由内容,客户关系梳理
  • 原文地址:https://www.cnblogs.com/williamwsj/p/9715849.html
Copyright © 2011-2022 走看看