Swoole4 協程的出現使得 PHP 底層上從原來串行模式變成了併發模式。有不少 PHP 的C/C++
擴展在開發時未能考慮到併發性、可重入問題,致使沒法在Swoole
協程中使用。本文會詳細講解如何編寫協程併發安全的C/C++
代碼。編程
示例代碼:安全
int t; void test1(int *x, int *y) { t = *x; *x = *y; //fun1 函數中可能會存在協程切換 fun1(); //錯誤代碼 *y = t; }
t
是一個全局變量或者static
靜態變量A
中調用了test1
函數,使用了全局變量t
fun1()
,這個函數中若是發生了協程切換,這時假如另一個協程B
也執行了test1
函數,那麼t
的值可能會被修改B
掛起時,從新回到協程A
,這時*y = t
,會獲得一個錯誤的值這也是一個嚴重的風險點。協程1
將自身棧內存的指針發送給另一個協程2
,協程1
退出時會釋放協程棧內存。協程2
的生命週期長於1
,繼續讀寫此內存,就會致使segment fault
。併發
示例:函數
void co1() { char buf[2048]; //這裏啓動一個新的協程,buf 是協程1棧上內存 co2(buf); //協程1 退出時會釋放棧內存 } void co2(char *buf) { for(int i=0; i<2048; i++) { Coroutine::sleep(1); //這裏 buf 內存可能已經釋放了 buf[i] = 1; } }
爲了保證安全性,在Swoole4
協程編程中:指針
static
變量和全局變量,堅持只用局部變量IO
或Sleep
等引發協程切換的操做