天天看点

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

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

<a id="markdown-1-aspnet-core-mvc-io编程模型" name="1-aspnet-core-mvc-io编程模型"></a>

<!-- TOC -->

  • 1. ASP.NET Core MVC I/O编程模型
    • 1.1. I/O编程模型浅析
    • 1.2. 同步阻塞I/O
    • 1.3. 同步非阻塞I/O
    • 1.4. 异步I/O
    • 1.5. 总结

<!-- /TOC -->

<a id="markdown-11-io编程模型浅析" name="11-io编程模型浅析"></a>

服务器端编程经常需要构造高性能的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操作彻底完成。

<a id="markdown-12-同步阻塞io" name="12-同步阻塞io"></a>

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

在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);
        }
           

<a id="markdown-13-同步非阻塞io" name="13-同步非阻塞io"></a>

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

在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);
    }

           

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

如果想在同步非阻塞的情况下获得返回的数据,就需要轮询,重复的对线程请求。代码清单中使用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);
    }

           

<a id="markdown-14-异步io" name="14-异步io"></a>

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

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;
    }

           

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

<a id="markdown-15-总结" name="15-总结"></a>

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

以上内容有任何错误或不准确的地方请大家指正,不喜勿喷!

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果觉得还有帮助的话,可以点一下右下角的【推荐】,希望能够持续的为大家带来好的技术文章!想跟我一起进步么?那就【关注】我吧。