PHP 多進(jìn)程

簡(jiǎn)單的父子進(jìn)程

<?php
  
/**
 * 簡(jiǎn)單的父子進(jìn)程
 * pcntl_fork 創(chuàng)建了一個(gè)子進(jìn)程,父進(jìn)程和子進(jìn)程都從 fork 位置開始向下繼續(xù)執(zhí)行,不同的是父進(jìn)程執(zhí)行過程中,得到的 fork 返回值為子進(jìn)程號(hào),而子進(jìn)程得到的是 0。
 * posix_getpid 獲取當(dāng)前進(jìn)程
 * posix_getppid 獲取父親進(jìn)程
 */
// fork 父進(jìn)程中返回的是子進(jìn)程號(hào)、子進(jìn)程中返回的是 0
$pid = pcntl_fork();
if (0 === $pid) {
    echo "子進(jìn)程:" . posix_getpid() . " - 父進(jìn)程:". posix_getppid() . PHP_EOL;
} elseif ($pid > 0) {
    echo "父進(jìn)程:" . posix_getpid() . " - 子進(jìn)程:". $pid . PHP_EOL;
} else {
    throw \Exception("進(jìn)程 fork 錯(cuò)誤");
}

// 輸出:
// 父進(jìn)程:292 - 子進(jìn)程:293
// 子進(jìn)程:293 - 父進(jìn)程:292

循環(huán)內(nèi)父子進(jìn)程

<?php

/**
 * fork 一次調(diào)用,兩次返回
 * 如果子進(jìn)程不加 exit 退出的話,子進(jìn)程也會(huì)參與到循環(huán),然后子進(jìn)程 fork 新的子進(jìn)程
 */
for ($i = 1; $i <= 3; $i++) {
    $pid = pcntl_fork();
    if (0 === $pid) {
        echo "子進(jìn)程:" . $pid . PHP_EOL;
        // for 循環(huán)里使用 pcntl_fork() 需要 exit,否則會(huì)造成進(jìn)程分裂
        // exit;
    }
}

// 輸出:
// 子進(jìn)程:0
// 子進(jìn)程:0
// 子進(jìn)程:0
// 子進(jìn)程:0
// 子進(jìn)程:0
// 子進(jìn)程:0
// 子進(jìn)程:0
image-20210706080335902

多個(gè)進(jìn)程復(fù)用一個(gè)鏈接

<?php
  
/**
 * 多個(gè)進(jìn)程共享一個(gè)鏈接問題
 * - 多個(gè)進(jìn)程復(fù)用一個(gè)連接會(huì)造成結(jié)果無法保證被哪個(gè)進(jìn)程處理
 * - 正確做法應(yīng)該是給每一個(gè)進(jìn)程分別創(chuàng)建一個(gè)連接
 */
$redis = new Redis();
// 此處只創(chuàng)建一個(gè)連接,在后續(xù)給多個(gè)進(jìn)程復(fù)用數(shù)據(jù)會(huì)發(fā)生錯(cuò)亂了,此處應(yīng)被注釋
$redis->connect('docker-lnmp_redis_1', 6379);
for ($i = 1; $i <= 4; $i++) {
    $pid = pcntl_fork();
    if (0 === $pid) {
        // 正確做法:注釋上面共享的連接,給每一個(gè)進(jìn)程分別創(chuàng)建一個(gè) Redis 連接
        // $redis->connect('docker-lnmp_redis_1', 6379);
        // uid 只有 [1,2,3,5],沒有 4
        $res = $redis->sIsMember('uid', $i);
        echo $i . ":" . json_encode($res) . PHP_EOL;
        while (true) {
            sleep(1);
        }
    }
}
while (true) {
    sleep(1);
}
image-20210706085902625

多個(gè)進(jìn)程復(fù)用一個(gè)鏈接會(huì)導(dǎo)致判斷錯(cuò)誤,此處就判斷存在的 3 居然為 false,并且 4 沒輸出

image-20210706085934356

使用 netstat 和 ps 查看多個(gè)進(jìn)程使用了一個(gè)鏈接

image

而更改為一個(gè)進(jìn)程一個(gè)連接,就能正常輸出,不過是無序的,這一點(diǎn)要注意

image-20210706090513920

進(jìn)程查看

image-20210706091116530
image-20210706091138214
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容