什么是行程、執行緒、協程
行程 Process
- 計算機中的程式關于某資料集合上的一次運行活動,“一個執行中的程式”
- 系統進行資源分配和調度的基本單位
- 三態模型:
多道程式系統中,行程在處理器上交替運行,狀態不斷地發生變化- 運行:正在處理機上運行;
- 就緒:當一個行程獲得了除處理機以外的一切所需資源,一旦得到處理機即可運行,則稱處于就緒狀態,可按多個優先級來劃分佇列,如,當一個行程由于時間片用完而進入就緒狀態時,排入低優先級;當行程由IO操作完成而進入就緒狀態時,排入高優先級佇列,
- 阻塞:也稱為等待或睡眠狀態,一個行程正在等待某一事件發生(例如請求IO而等待IO完成等)而暫時停止運行,這時即使把處理機分配給行程也無法運行,
- 五態模型:
- 新建態:行程剛剛被創建時沒有被提交的狀態,等待系統完成創建行程的所有必要資訊,
- 活躍就緒/靜止就緒:
- 活躍就緒,指行程在主存并且可被調度的狀態;
- 靜止就緒,是指行程被對換到輔存時的就緒狀態,是不能被直接調度的狀態,只有當主存中沒有活躍就緒態行程,或者是掛起就緒態行程具有更高的優先級,系統將把掛起就緒態行程調回主存并轉換為活躍就緒,
- 運行:-
- 活躍阻塞/靜止阻塞:
- 活躍阻塞,是指行程已在主存,一旦等待的事件發生便進入活躍就緒狀態;
- 靜止阻塞,行程對換到輔存時的阻塞狀態,一旦等待的事件發生便進入靜止就緒狀態,
- 終止態:行程已結束運行,回收除行程控制塊之外的其他資源,并讓其他行程從行程控制塊中收集有關資訊,
執行緒 Thread
- 有時被稱為輕量級行程(LightWeight Process, LWP),程式執行流的最小單元,
- 一個相對獨立的、可調度的執行單元,系統獨立調度和分配CPU的基本單位,
- 共享行程的地址空間和資源,
- 狀態:就緒、阻塞、運行
- 就緒狀態:具備運行的所有條件,邏輯上可以運行,在等待處理機
- 運行狀態:占有處理機正在運行
- 阻塞狀態:在等待一個事件(如某個信號量),邏輯上不可執行
協程 Coroutine
- 一種用戶態的輕量級執行緒,調度完全由用戶控制
- 擁有自己的暫存器背景關系和堆疊
- 調度切換時,將暫存器背景關系和堆疊保存到其他地方,切回來的時候恢復,基本沒有內核切換的開銷
- 可以不加鎖的訪問全域變數
- 異步
什么是多行程、多執行緒
多行程
同一個時間里,同一個計算機系統中如果允許兩個或兩個以上的行程處于運行狀態,就是多行程
多執行緒
單個程式中同時運行多個執行緒完成不同的作業,就是多執行緒
同步阻塞模型
多行程,最早的服務端程式都是通過多行程、多執行緒來解決并發IO的問題;
一個請求創建一個行程,然后子行程進入回圈同步堵塞地與客戶端連接進行互動,收發處理資料,
多執行緒,用多執行緒模式實作非常簡單,執行緒中直接向某一個客戶端連接發送資料,
缺點
- 嚴重依賴行程的數量解決并發問題
- 啟動大量行程會帶來額外的行程調度消耗

異步非阻塞模型
- select 系統的查詢,一個行程內建立1024個連接,
poll模型,回圈檢測是否有連接, - 現在各種高并發異步IO的服務器程式都是基于
epoll實作的, - IO復用異步非阻塞程式使用經典的
Reactor模型,顧名思義就是反應堆的意思,本身不處理任何資料收發,只是可以監視一個socket句柄的事件變化,
Reactor模型
- Add: 添加一個socket到Reactor
- Set: 修改socket對應的事件,如可讀可寫
- Del: 從Reactor中移除,不再監聽事件
- Callback: 事件發生后回呼指定的函式
Nginx:多執行緒Reactor
Swoole:多執行緒Reactor + 多行程Worker

PHP并發編程實踐
Swoole擴展
- 異步、并行、高性能網路通信引擎,使用C語言撰寫,提供了PHP語言的異步多執行緒服務器,異步TCP/UDP網路客戶端,異步MySQL,異步Redis,資料庫連接池,AsyncTask,訊息佇列,毫秒定時器,異步檔案讀寫,異步DNS查詢
- 為PHP多行程的模式設計了多個并發資料結構和IPC通信機制,可以大大簡化多行程并發編程的作業
- Swoole2.0支持了類似Go語言的協程,可以使用完全同步的代碼實作異步程式
訊息佇列
- 經典場景,
- 注冊成功后發送郵件,發送短信
- 串行方式:注冊成功后,先發送郵件,在發送短信
- 并行方式:注冊成功后,同時發送郵件和短信
- 訊息佇列方式(離線方式):注冊成功后,將成功訊息寫入佇列,此時直接回傳成功給用戶,寫入佇列的時間非常短,可以忽略不計,然后異步發送郵件和短信 -
- 應用解耦
- 場景說明:用戶下單后,訂單系統需要通知庫存系統,
- 假如庫存系統無法訪問,則訂單減庫存將失敗,從而導致訂單失敗,
- 訂單系統與庫存系統耦合
- 參考佇列,用戶下單后,訂單系統完成持久化處理,將訊息寫入訊息佇列,回傳用戶訂單下單成功,
- 訂閱下單的訊息,采用拉/推的方式,獲取下單資訊,庫存系統根據下單資訊,進行庫存操作,
- 流量削峰
- 秒殺活動,流量瞬時激增,服務器壓力過大,
- 用戶發起請求,服務器接收后,先寫入訊息佇列,假如訊息佇列長度超過最大值,則直接報錯或提示用戶,
- 后續程式讀取訊息佇列再做處理,
- 控制請求量,緩解高流量,
- 日志處理
- 場景:解決大量日志的傳輸
- 日志采集程式將程式寫入訊息佇列,然后通過日志處理程式的訂閱消費日志,
- 訊息通訊
- 場景:聊天室
- 多個客戶端訂閱同一主題,進行訊息發布和接收
- 常見訊息佇列產品
- Kafka
- ActiveMQ
- ZeroMQ
- RabbitMQ
- Redis
介面的并發請求
curl_multi_init
參看
- The way of PHP concurrent IO programming
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/254682.html
標籤:PHP
