91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PHP PCNTL多進程編程

發布時間:2020-06-01 19:56:52 來源:網絡 閱讀:1581 作者:yorkershi 欄目:web開發

PHP中的PCNTL可以實現多進程編程,由于項目場景需要,試用了一下,感觸頗多,也長了不少見識,就此對遇到的問題小做一個總結,以備不時之需。


問題一:fork泛濫

我想在一個父進程中起10個子程來完成我的工作,代碼如下:

for($i = 0; $i < 10; $i++) {
    $pid = pcntl_fork();
    if($pid  == -1) {
        echo "Could not fork!\n";
        exit(1);
    }
    if(!$pid) {
        //child process workspace
        //TODO
        Api::refreshCache();        
    }
}

由于Api::refreshCache邏輯中有數據庫操作,代碼一執行,就把DB搞死了,報了N多個too many connections。我以為是DB原本就抽風了,檢查DB,正常。

最終發現,這一段代碼fork的可不是10個子進程,而是

20 + 21 + 22+ 23 + 24 + ... + 29 = 210-1 = 1023 個子進程。

恐怖了吧?這是因為子進程又fork子進程,并且子進程不共享父進程$i變量更新的值,由此導致數量成指數關系增長。

為了避免這個問題,代碼修改如下:

for($i = 0; $i < 10; $i++) {
    $pid = pcntl_fork();
    if($pid  == -1) {
        echo "Could not fork!\n";
        exit(1);
    }
    if(!$pid) {
        //child process workspace
        //TODO
        Api::refreshCache(); 
        exit; //子進程邏輯執行完后,馬上退出,以免往下走再fork子進程,不好控制     
    }
}

只要在子進程邏輯執行完后,加一個exit,一切都在撐握中了。這樣,只有一個父進程,父進程后續對子進程的管理也會清晰很多。


問題二:單例模式下DB連接被虐

/*
 * 前面或遠或近的地方,已經有一個$db = &MySql::getInstance();了
 */
for($i = 0; $i < 10; $i++) {
    $pid = pcntl_fork();
    if($pid  == -1) {
        echo "Could not fork!\n";
        exit(1);
    }
    if(!$pid) {
        //child process workspace
        //TODO
        $db = &MySql::getInstance();
        $sql = "XXX";
        $result = $db->getAll($sql);
        exit;
    }
}

這段代碼,十有八九都會報mysql has gone away.或者其它一些數據fetch方面的錯誤。究其原因,是因為各個子進程創建時,就已經繼承了父進程一份完全一樣的拷貝。對象可以拷貝,但是已創建的連接可不能拷貝成多個,由此產生的結果,就是各個進程都使用同一個mysql連接,各干各的事,最終產生莫名其妙的沖突。

解決辦法:

我們顯然不可能完全保證在fork進程之前,父進程不會創建mysql連接實例,因此,解決方案只能靠子進程本身了。可以想象,我們只需要在子進程中獲取的實例只與當前進程相關,這個問題就不存在了。解決辦法就是稍微改造一下mysql類實例化的靜態方式,與當前進程ID綁定。

public static function &getInstance() {
    static $instances = array();
    $key = getmypid(); //獲取當前進程ID
    if(empty($instances[$key])) {
        //實例化mysql類動作
        $classname = __CLASS__;
        $instances[$key] = new $classname();
    }
    return $instances[$key];
}


總結:子進程創建時,拷貝了父進程當時擁有的所有資源,雖說后面對資源的修改互不影響,但DB連接卻還是同一個,造成運行混亂。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

盐山县| 沙湾县| 甘德县| 开封市| 永福县| 郑州市| 锡林郭勒盟| 平利县| 白玉县| 望奎县| 永寿县| 依安县| 康马县| 绍兴县| 梓潼县| 北京市| 连城县| 怀集县| 奉节县| 峨眉山市| 宣化县| 武宁县| 莒南县| 怀化市| 措美县| 芦山县| 湖口县| 双辽市| 永济市| 乌恰县| 株洲市| 安图县| 和政县| 汝阳县| 定结县| 资兴市| 基隆市| 桑植县| 镇安县| 甘南县| 西充县|