協程與線程的區別(swoole版解析)


 

注意,協程的客戶端內執行其實是同步的,不要理解為異步,它只是遇到IO阻塞時能讓出執行權,切換到其他協程而已,不能和異步混淆。

 

一 概念

  1. 進程是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。每個進程都有自己的獨立內存空間,不同進程通過進程間通信來通信。由於進程比較重量,占據獨立的內存,所以上下文進程間的切換開銷(棧、寄存器、虛擬內存、文件句柄等)比較大,但相對比較穩定安全。
  2. 線程是指進程內的一個執行單元,也是進程內的可調度實體。線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。線程間通信主要通過共享內存,上下文切換很快,資源開銷較少,但相比進程不夠穩定容易丟失數據。
  3. 協程是一種用戶態的輕量級線程,協程的調度完全由用戶控制。從技術的角度來說,“協程就是你可以暫停執行的函數”。協程擁有自己的寄存器上下文和棧。協程調度切換時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢復先前保存的寄存器上下文和棧,直接操作棧則基本沒有內核切換的開銷,可以不加鎖的訪問全局變量,所以上下文的切換非常快。

 

二 協程與線程的區別

  1. 一個線程可以多個協程,一個進程也可以單獨擁有多個協程。
  2. 協程能保留上一次調用時的狀態,每次過程重入時,就相當於進入上一次調用的狀態。
  3. 線程是搶占式,而協程是非搶占式的,所以需要用戶自己釋放使用權來切換到其他協程,因此同一時間其實只有一個協程擁有運行權,相當於單線程的能力。
  4. 協程並不是取代線程, 而且抽象於線程之上, 線程是被分割的CPU資源, 協程是組織好的代碼流程, 協程需要線程來承載運行, 線程是協程的資源, 但協程不會直接使用線程, 協程直接利用的是執行器(Interceptor), 執行器可以關聯任意線程或線程池, 可以使當前線程, UI線程, 或新建新程.。
  5. 線程是協程的資源。協程通過Interceptor來間接使用線程這個資源

 

三 PHP7.2協程改動

在 PHP-7.2 版本中底層會分配 8K 的 stack 來存儲協程的變量,zval 的尺寸為 16字節,因此 8K 的 stack 最大可以保存 512 個變量。協程棧內存占用超過 8K 后 ZendVM 會自動擴容

PHP-7.1、PHP-7.0 默認會分配 256K 棧內存

 

四 SWOOLE中協程數量

max_coroutine設置當前工作進程最大協程數量。超過max_coroutine底層將無法創建新的協程,底層會拋出錯誤,並直接關閉連接。

在Server程序中實際最大可創建協程數量等於 worker_num * max_coroutine

$server->set(array(
'max_coroutine' => 3000,
))

默認值為3000

 

五 當前項目的數據庫連接池的協程channel

 
  • 通道與PHPArray類似,僅占用內存,沒有其他額外的資源申請,所有操作均為內存操作,無IO消耗
  • 底層使用PHP引用計數實現,無內存拷貝。即使是傳遞巨大字符串或數組也不會產生額外性能消耗
  • swoole中channel與go的區別是,增加了最大讀取時間參數,當超過此事件未得到消費數據或者未能新增消費數據自動拋出異常
consumer_num 消費者數量,表示當前通道為空,有N個協程正在等待其他協程調用push方法生產數據
producer_num 生產者數量,表示當前通道已滿,有N個協程正在等待其他協程調用pop方法消費數據
queue_num 通道中的元素數量

array(
"consumer_num" => 0,
"producer_num" => 1,
"queue_num" => 10
);

 

六 當協程是處理IO阻塞較多的場景

 
個人理解:只要碰到IO阻塞,就跳出go函數,IO阻塞完成后就跳回go函數里

協程並不是一定縮短代碼的執行時間,我在測試的發現:
1.沒有io阻塞時,多個go運行切換,執行順序是和正常的串行代碼一樣,但是消費的時間卻比正常時間要高。
2.有io阻塞時,時間也是比正常時間要高。

因此 我個人認為協程的使用要注重場景,然后得達到比較高的並發量了才應當使用它來開發業務
比如:雲盤系統,大文件下載,1G的文件,我們可以把文件分成n份,n份文件對應n個協程去處理,那效率和時間自然沒得說了


免責聲明!

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



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