摘要:有很多的擴展在開發(fā)時未能考慮到并發(fā)性可重入問題,導致無法在協(xié)程中使用。本文會詳細講解如何編寫協(xié)程并發(fā)安全的代碼。協(xié)程將自身棧內(nèi)存的指針發(fā)送給另外一個協(xié)程,協(xié)程退出時會釋放協(xié)程棧內(nèi)存。協(xié)程的生命周期長于,繼續(xù)讀寫此內(nèi)存,就會導致。
Swoole4 協(xié)程的出現(xiàn)使得 PHP 底層上從原來串行模式變成了并發(fā)模式。有很多 PHP 的C/C++擴展在開發(fā)時未能考慮到并發(fā)性、可重入問題,導致無法在Swoole協(xié)程中使用。本文會詳細講解如何編寫協(xié)程并發(fā)安全的C/C++代碼。
可重入性示例代碼:
int t; void test1(int *x, int *y) { t = *x; *x = *y; //fun1 函數(shù)中可能會存在協(xié)程切換 fun1(); //錯誤代碼 *y = t; }
t是一個全局變量或者static靜態(tài)變量
在協(xié)程A中調(diào)用了test1函數(shù),使用了全局變量t
當函數(shù)內(nèi)調(diào)用了fun1(),這個函數(shù)中如果發(fā)生了協(xié)程切換,這時假如另外一個協(xié)程B也執(zhí)行了test1函數(shù),那么t的值可能會被修改
協(xié)程B掛起時,重新回到協(xié)程A,這時*y = t,會得到一個錯誤的值
引用棧內(nèi)存這也是一個嚴重的風險點。協(xié)程1將自身棧內(nèi)存的指針發(fā)送給另外一個協(xié)程2,協(xié)程1退出時會釋放協(xié)程棧內(nèi)存。協(xié)程2的生命周期長于1,繼續(xù)讀寫此內(nèi)存,就會導致segment fault。
示例:
void co1() { char buf[2048]; //這里啟動一個新的協(xié)程,buf 是協(xié)程1棧上內(nèi)存 co2(buf); //協(xié)程1 退出時會釋放棧內(nèi)存 } void co2(char *buf) { for(int i=0; i<2048; i++) { Coroutine::sleep(1); //這里 buf 內(nèi)存可能已經(jīng)釋放了 buf[i] = 1; } }協(xié)程安全代碼
為了保證安全性,在Swoole4協(xié)程編程中:
不要使用static變量和全局變量,堅持只用局部變量
若必須訪問全局變量,必須保證只用于計算邏輯,不得存在任何IO或Sleep等引起協(xié)程切換的操作
不調(diào)用其它任何不可重入的函數(shù)
不要引用棧上內(nèi)存
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/31013.html
摘要:下文如無特殊聲明將使用進程同時表示進程線程。收到數(shù)據(jù)后服務器程序進行處理然后使用向客戶端發(fā)送響應。現(xiàn)在各種高并發(fā)異步的服務器程序都是基于實現(xiàn)的,比如。 并發(fā) IO 問題一直是服務器端編程中的技術難題,從最早的同步阻塞直接 Fork 進程,到 Worker 進程池/線程池,到現(xiàn)在的異步IO、協(xié)程。PHP 程序員因為有強大的 LAMP 框架,對這類底層方面的知識知之甚少,本文目的就是詳細介...
摘要:第一階段基礎階段基礎程序員重點把搞熟練核心是安裝配置基本操作目標能夠完成基本的系統(tǒng)安裝,簡單配置維護能夠做基本的簡單系統(tǒng)的開發(fā)能夠在中型系統(tǒng)中支持某個功能模塊的開發(fā)。本項不做重點學習,除非對前端有興趣。 第一階段:基礎階段(基礎PHP程序員) 重點:把LNMP搞熟練(核心是安裝配置基本操作) 目標:能夠完成基本的LNMP系統(tǒng)安裝,簡單配置維護;能夠做基本的簡單系統(tǒng)的PHP開發(fā);能夠在P...
閱讀 1280·2021-09-27 13:35
閱讀 2581·2021-09-06 15:12
閱讀 3395·2019-08-30 15:55
閱讀 2853·2019-08-30 15:43
閱讀 444·2019-08-29 16:42
閱讀 3458·2019-08-29 15:39
閱讀 3075·2019-08-29 12:28
閱讀 1254·2019-08-29 11:11