• ASP.NET Core MVC I/O编程模型


    1.1. I/O编程模型浅析

    服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:

    (1)同步阻塞IO(Blocking IO):即传统的IO模型。

    (2)同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK。

    (3)IO多路复用(IO Multiplexing):即经典的Reactor设计模式,有时也称为异步阻塞IO,Java中的Selector和Linux中的epoll都是这种模型。

    (4)异步IO(Asynchronous IO):即经典的Proactor设计模式,也称为异步非阻塞IO。

    同步和异步的概念描述的是用户线程与内核的交互方式:

    • 同步是指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行;

    • 异步是指用户线程发起IO请求后仍继续执行,当内核IO操作完成后会通知用户线程,或者调用用户线程注册的回调函数。

    阻塞和非阻塞的概念描述的是用户线程调用内核IO操作的方式:

    • 阻塞是指IO操作需要彻底完成后才返回到用户空间;

    • 非阻塞是指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。

    1.2. 同步阻塞I/O

    同步阻塞I/O模型是最简单的I/O模型,用户进程在进行I/O操作时被阻塞,如下图所示:

    2017-08-27-15-47-15

    在ASP.NET Core中没有使用多线程或加入异步关键字的模型均为同步阻塞I/O

    
         public IActionResult Sync()
            {
                var start = DateTime.Now;
                Add();
                return Json("start:"+start+"||| end:" + DateTime.Now);
            }
    
               void Add()
            {
                Thread.Sleep(2000);
                Console.WriteLine(DateTime.Now);
            }
    

    2017-09-03-11-48-07

    1.3. 同步非阻塞I/O

    在同步非阻塞整个IO请求的过程中,虽然用户线程每次发起IO请求后可以立即返回,但是为了等到数据,仍需要不断地轮询、重复请求,消耗了大量的CPU的资源。一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性

    2017-09-03-11-00-36

    在ASP.NET Core 中可以使用多线程来实现同步非阻塞,在如下代码清单中可以看到,使用多线程调用一个会自动休眠2秒的方法,主线程Sync会先返回值,而不会阻塞。

    
        public IActionResult Sync()
        {
            var thread = new Thread(new ThreadStart(this.Add));
            thread.Start();
            return Json(DateTime.Now);
        }
    
        void Add()
        {
            Thread.Sleep(2000);
            Console.WriteLine(DateTime.Now);
        }
    
    

    2017-09-03-11-45-12

    而子线程由于被阻塞了2秒,因此时间为:

    2017-09-03-11-45-59

    如果想在同步非阻塞的情况下获得返回的数据,就需要轮询,重复的对线程请求。代码清单中使用while循环轮询线程。

    
       public IActionResult Sync()
        {
            short num = 10;
            var thread = new Thread(new ParameterizedThreadStart(this.Add));
            thread.Start(num);
            while (thread.IsAlive) ;
            return Json(DateTime.Now + "result:" + result);
        }
    
        void Add(object num)
        {
            Thread.Sleep(2000);
            this.result =(short)num ;
            Console.WriteLine(DateTime.Now);
        }
    
    

    2017-09-03-12-03-05

    1.4. 异步I/O

    真正的异步IO需要操作系统更强的支持。在异步IO模型中,当用户线程收到通知时,数据已经被内核读取完毕,并放在了用户线程指定的缓冲区内,内核在IO完成后通知用户线程直接使用即可。

    2017-09-03-12-31-32

    
      public IActionResult Async()
        {
            var start = DateTime.Now;
            short num = 10;
            var result = Add(num).Result;
            return Json("start:"+ start +" end: " +  DateTime.Now + " ||| result: " + result);
        }
    
        async Task<short> Add(short num)
        {
            await Task.Delay(2000);
            return ++num;
        }
    
    

    2017-09-03-12-42-53

    关于异步的更详细的使用可参看 http://www.cnblogs.com/vipyoumay/p/5663950.html

    1.5. 总结

    1.同步与异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)

    所谓同步,就是在发出一个 调用 时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由调用者主动等待这个调用的结果。而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。

    你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。

    2. 阻塞与非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.

    阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

    你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关


    【1】http://www.jianshu.com/p/77332a3b07b5

    【2】http://kb.cnblogs.com/page/85931

    【3】https://www.zhihu.com/question/19732473

    作者:帅虫哥 出处: http://www.cnblogs.com/vipyoumay/p/7487389.html

  • 相关阅读:
    LeetCode 264. Ugly Number II
    LeetCode 231. Power of Two
    LeetCode 263. Ugly Number
    LeetCode 136. Single Number
    LeetCode 69. Sqrt(x)
    LeetCode 66. Plus One
    LeetCode 70. Climbing Stairs
    LeetCode 628. Maximum Product of Three Numbers
    Leetcode 13. Roman to Integer
    大二暑假周进度报告03
  • 原文地址:https://www.cnblogs.com/vipyoumay/p/7487389.html
Copyright © 2020-2023  润新知