<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                在學習異步IO模型前,我們先來了解協程。 協程,又稱微線程,纖程。英文名Coroutine。 協程的概念很早就提出來了,但直到最近幾年才在某些語言(如Lua)中得到廣泛應用。 子程序,或者稱為函數,在所有語言中都是層級調用,比如A調用B,B在執行過程中又調用了C,C執行完畢返回,B執行完畢返回,最后是A執行完畢。 所以子程序調用是通過棧實現的,一個線程就是執行一個子程序。 子程序調用總是一個入口,一次返回,調用順序是明確的。而協程的調用和子程序不同。 協程看上去也是子程序,但執行過程中,在子程序內部可中斷,然后轉而執行別的子程序,在適當的時候再返回來接著執行。 注意,在一個子程序中中斷,去執行其他子程序,不是函數調用,有點類似CPU的中斷。比如子程序A、B: ~~~ def A(): print('1') print('2') print('3') def B(): print('x') print('y') print('z') ~~~ 假設由協程執行,在執行A的過程中,可以隨時中斷,去執行B,B也可能在執行過程中中斷再去執行A,結果可能是: ~~~ 1 2 x y 3 z ~~~ 但是在A中是沒有調用B的,所以協程的調用比函數調用理解起來要難一些。 看起來A、B的執行有點像多線程,但協程的特點在于是一個線程執行,那和多線程比,協程有何優勢? 最大的優勢就是協程極高的執行效率。因為子程序切換不是線程切換,而是由程序自身控制,因此,沒有線程切換的開銷,和多線程比,線程數量越多,協程的性能優勢就越明顯。 第二大優勢就是不需要多線程的鎖機制,因為只有一個線程,也不存在同時寫變量沖突,在協程中控制共享資源不加鎖,只需要判斷狀態就好了,所以執行效率比多線程高很多。 因為協程是一個線程執行,那怎么利用多核CPU呢?最簡單的方法是多進程+協程,既充分利用多核,又充分發揮協程的高效率,可獲得極高的性能。 Python對協程的支持是通過generator實現的。 在generator中,我們不但可以通過`for`循環來迭代,還可以不斷調用`next()`函數獲取由`yield`語句返回的下一個值。 但是Python的`yield`不但可以返回一個值,它還可以接收調用者發出的參數。 來看例子: 傳統的生產者-消費者模型是一個線程寫消息,一個線程取消息,通過鎖機制控制隊列和等待,但一不小心就可能死鎖。 如果改用協程,生產者生產消息后,直接通過`yield`跳轉到消費者開始執行,待消費者執行完畢后,切換回生產者繼續生產,效率極高: ~~~ def consumer(): r = '' while True: n = yield r if not n: return print('[CONSUMER] Consuming %s...' % n) r = '200 OK' def produce(c): c.send(None) n = 0 while n < 5: n = n + 1 print('[PRODUCER] Producing %s...' % n) r = c.send(n) print('[PRODUCER] Consumer return: %s' % r) c.close() c = consumer() produce(c) ~~~ 執行結果: ~~~ [PRODUCER] Producing 1... [CONSUMER] Consuming 1... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 2... [CONSUMER] Consuming 2... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 3... [CONSUMER] Consuming 3... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 4... [CONSUMER] Consuming 4... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 5... [CONSUMER] Consuming 5... [PRODUCER] Consumer return: 200 OK ~~~ 注意到`consumer`函數是一個`generator`,把一個`consumer`傳入`produce`后: 1. 首先調用`c.send(None)`啟動生成器; 2. 然后,一旦生產了東西,通過`c.send(n)`切換到`consumer`執行; 3. `consumer`通過`yield`拿到消息,處理,又通過`yield`把結果傳回; 4. `produce`拿到`consumer`處理的結果,繼續生產下一條消息; 5. `produce`決定不生產了,通過`c.close()`關閉`consumer`,整個過程結束。 整個流程無鎖,由一個線程執行,`produce`和`consumer`協作完成任務,所以稱為“協程”,而非線程的搶占式多任務。 最后套用Donald Knuth的一句話總結協程的特點: “子程序就是協程的一種特例。” ### 參考源碼 [coroutine.py](https://github.com/michaelliao/learn-python3/blob/master/samples/async/coroutine.py)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看