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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM