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

                # 協程 協程說復雜不復雜說難也不難,一句話可以概括:能提高并發,但不能加速任務,同步代碼實現異步IO,異步非阻塞的代碼塊。 協程是一種特殊函數,是一種可以掛起的函數,然后可以從掛起的地方重新恢復執行,一個線程內的多個協程是串行的,跟CPU處理進程一樣,同一時刻只能一個協程在線程上運行,除非出讓了控制權給別的協程運行。協程無法利用多核CPU因此協程只能解決并發問題,不能解決任務處理速度問題。協程就是把一個大任務再分成更小的片段,封裝程一個函數,當其中一個協程需要IO阻塞的時候,主動掛起當前協程,把控制權交給其他協程運行。 我們知道進程和線程是由操作系統調度的,什么時候執行取決于操作系統什么時候把CPU時間交給某個進程或者線程,而協程是什么時候交出控制權是由用戶決定的。進程和線程屬于內核態,協程屬于用戶態線程。 協程是一種用戶態的輕量級線程,協程的調度完全由用戶控制。協程擁有自己的寄存器上下文和棧。協程調度切換時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢復先前保存的寄存器上下文和棧,直接操作棧則基本沒有內核切換的開銷,可以不加鎖的訪問全局變量,所以上下文的切換非常快。 ### 協程特點 * 1、用戶態線程、遇到IO主動讓出控制權 * 2、多個協程代碼依然是串行的,無需加鎖 * 3、開銷低,只占用內存,不存在進程、線程切換開銷 * 4、并發量大,單個進程可開啟50w個協程 * 5、隨時隨地,只要想并發,就調用go創建協程 ![](https://img.kancloud.cn/bc/b1/bcb155964abee12726c52719877382af_754x645.png) <center>圖:1.5-1</center> 我們知道線程是輕量級的進程,那么協程就是輕量級的線程。協程運行在線程之上,一個線程可以有多個協程。 我們知道在進程遇到阻塞的時候開多一個線程在進程內部切換,避免每次都切換進程,這樣可以更大力度的使用CPU分給這個進程的可使用時間。而協程跟線程和進程的關系很類似,只不過協程是跟線程直接建立關系。 ![](https://img.kancloud.cn/b3/02/b30265b2e38f39227518b6fd1b890317_2000x656.png) <center>圖:1.5-2</center> 圖:1.5-2 是多個線程之間切換的示意圖,那么我們來考慮一下,如果線程只是等待IO操作(網絡或者文件),那么為什么像線程重復使用進程一樣來重復的使用這個線程呢?我們把IO去掉,看看這個圖是什么樣子的。 ![](https://img.kancloud.cn/32/1a/321a9e35422fbefb09de47a56ae4e4ae_1504x494.png) <center>圖:1.5-3</center> 去掉IO部分操作,可以看出來基本上這個并發請求應用程序代碼可以在 `單個線程中` 運行,協程最大力度的利用了線程等待IO的時間,讓程序在等待IO的時候可以執行別的業務代碼。 ![](https://img.kancloud.cn/10/43/1043f5ab17933d4b062124a6eddba1f2_1176x632.png) <center>圖:1.5-4</center> 從圖:1.5-4 看著像不像一個線程的執行流程,這就是協程的魅力所在,當一個協程被yield之后會被掛起,把控制權轉移給線程內部的其他協程,因為是在線程上進行的切換,所以開銷遠遠比進程和線程低很多。 ![](https://img.kancloud.cn/1c/60/1c60d21a3d4072e840819d7c7272fdfa_2028x878.png) <center>圖:1.5-5</center> 當程序調用協程之后,當前協程會主動讓出控制權交給同一個線程內的其他協程處理,類似圖:1.5-5所示,開發者代碼中需要使用IO的時候主動讓出協程的控制權給別的協程使用。 ![](https://img.kancloud.cn/18/5f/185fd66abb2c80d129b503b2eb444b31_1834x806.png) <center>圖:1.5-6</center> 去掉IO部分再看協程的處理,就跟圖:1.5-4所示的一樣,直接執行的都是業務邏輯,避免遇到IO導致線程轉換到等待狀態,更充分的利用CPU分給這個線程的執行時間。 > 注意:協程并不能讓任務加速進行,只能執行更多任務。 協程由于是建立在線程之上的,因此沒有辦法使用CPU多核心的優勢,協程適合適用于IO密集運算的場景。 ### 協程有什么作用? 協程是為了提高CPU使用率,避免在線程阻塞的時候大量的線程上下文切換。 ```php echo "1-start\n"; sleep(1); echo "1-end\n"; echo "2-start\n"; sleep(1); echo "2-end\n"; echo "3-start\n"; sleep(1); echo "3-end\n"; echo "4-start\n"; sleep(1); echo "4-end\n"; ``` ![](https://img.kancloud.cn/ea/7e/ea7eee09bcb6113549793ba49e7de26b_574x207.png) <center>圖:1.5-7</center> 以上代碼的CPU使用率僅有`1%` ```php Swoole\Runtime::enableCoroutine(true); go(function () { echo "go1-start\n"; sleep(1); echo "go1-end\n"; }); go(function () { echo "go2-start\n"; sleep(1); echo "go2-end\n"; }); go(function () { echo "go3-start\n"; sleep(1); echo "go3-end\n"; }); go(function () { echo "go4-start\n"; sleep(1); echo "go4-end\n"; }); ``` ![](https://img.kancloud.cn/62/b1/62b16c26d4edf3497a3f591797a9362a_574x206.png) <center>圖:1.5-8</center> 使用協程,成功把CPU使用率提高到了`4%`,這樣CPU就不需要為了IO阻塞而空跑,或者進行上下文切換。之前不是說過協程不能加速嗎?這里使用協程之后怎么`1秒`多就執行完了,跟前面的代碼不一樣?這里得到的時間取決于最后一個協程執行結束的時間。 ### 協程的執行順序 ```php Swoole\Runtime::enableCoroutine(true); go(function(){ sleep(2); echo "go1\n"; }); go(function(){ sleep(1); echo "go2\n"; }); echo "main\n"; ``` 先輸出:main->go2->go1 ### 協程之間通訊 多個協程之間通訊,采用Channel實現,多個協程協助完成共同的任務。 ```php Swoole\Runtime::enableCoroutine(true); $chan = new Swoole\Coroutine\Channel(); go(function () use ($chan){ sleep(1); $chan->push(['name'=>'sunny']); }); go(function() use ($chan){ $data = $chan->pop(); print_r($data); }); echo "結束\n"; ```
                  <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>

                              哎呀哎呀视频在线观看