이 기사는 주로 PHP의 다중 프로세스 및 다중 스레딩 구현을 소개합니다. 이제는 모든 사람과 공유합니다. 도움이 필요한 친구들은 이를 참조할 수 있습니다.
고아 프로세스: 하나 하나 이상의 하위 프로세스가 실행 중인 동안 상위 프로세스가 종료되면 해당 하위 프로세스는 고아 프로세스가 됩니다. 고아 프로세스는 init 프로세스(프로세스 번호는 1)에 의해 채택되고 init 프로세스는 이에 대한 상태 수집 작업을 완료합니다.좀비 프로세스: 프로세스가 하위 프로세스를 생성하기 위해 포크를 사용하고 상위 프로세스가 하위 프로세스의 상태 정보를 얻기 위해 wait 또는 waitpid를 호출하지 않는 경우, 프로세스 설명자는 하위 프로세스는 여전히 시스템에 저장됩니다. 이 프로세스를 좀비 프로세스라고 합니다.
좀비 프로세스의 위험: 프로세스가 wait/waitpid를 호출하지 않으면
보유된 정보는 공개되지 않으며 해당 프로세스 번호는 항상 점유되지만 시스템은 사용되는 프로세스 번호는 제한되어 있습니다. 많은 수의 좀비 프로세스가 생성되면 사용 가능한 프로세스 번호가 없기 때문에 시스템에서 새 프로세스를 생성할 수 없습니다. 이는 좀비 프로세스의 피해이므로 피해야 합니다. 모든 하위 프로세스(init 제외)는 종료() 직후 사라지지 않고 좀비 프로세스(Zombie)라는 데이터 구조를 남기고 상위 프로세스가 처리될 때까지 기다립니다. 생성된 좀비 프로세스에 대한 솔루션: 상위 프로세스를 종료하면 생성된 좀비 프로세스는 고아 프로세스가 되며 이러한 고아 프로세스는 init 프로세스에 의해 인수됩니다. process will wait( ) 이러한 고아 프로세스는 자신이 차지하고 있는 시스템 프로세스 테이블의 리소스를 해제합니다.
좀비 프로세스에 대한 솔루션 (1) 신호 메커니즘을 통해
하위 프로세스가 종료되면 SIGCHILD 신호를 상위 프로세스로 보내고 상위 프로세스는 SIGCHILD 신호를 처리합니다. 좀비 프로세스를 처리하려면 신호 처리 함수에서 대기를 호출하세요.
(2) 두 번 포크"Unix 환경의 고급 프로그래밍"의 8.6절이 매우 자세합니다. 자식 프로세스를 고아(orphan) 프로세스로 만들어 부모 프로세스가 init 프로세스가 되고, 좀비 프로세스는 init 프로세스를 통해 처리될 수 있도록 하는 것이 원칙이다.
크기 비교
멀티 프로세싱
| 멀티스레딩
| 요약
|
데이터 공유 및 동기화 | 데이터 공유는 복잡하고 IPC가 필요하며 동기화가 간단합니다.프로세스 데이터가 공유되기 때문에 데이터 공유는 간단하지만 그렇기 때문에 동기화가 복잡하기도 합니다 |
각각의 장점이 있습니다 |
메모리, CPU |
를 차지합니다 많은 메모리, 복잡한 전환, CPU 사용률 낮음 |
적은 메모리 차지, 간단한 전환, 높은 CPU 사용률 |
스레드 지배력 |
||
생성, 파괴, 전환 |
복잡한 생성, 파괴, 스위칭, 느림 |
생성 파괴 및 스위칭이 간단하고 빠릅니다 |
스레드가 지배적입니다 |
||
프로그래밍 및 디버깅 |
간단한 프로그래밍 및 디버깅 |
복잡한 프로그래밍 및 복잡한 디버깅 |
프로세스가 지배합니다 |
||
신뢰성 |
프로세스가 서로 영향을 주지 않습니다 |
스레드 하나가 중단되면 전체 프로세스가 중단됩니다 |
프로세스가 지배합니다 | ||
분산됨 | 멀티 코어 및 멀티 머신 배포에 적합하며 하나의 머신으로 충분하지 않은 경우 여러 머신으로 확장하기가 더 쉽습니다 |
멀티 코어 배포에 적응 |
프로세스 우위 |
1) 자주 생성하고 폐기해야 하는 우선순위 스레드
이유는 위 비교를 참조하세요.
이 원칙의 가장 일반적인 적용은 웹 서버입니다. 연결이 끊어지면 스레드가 파괴됩니다. 프로세스를 사용하면 생성 및 파괴 비용이 감당할 수 없습니다
2) A. 많은 계산이 필요합니다 스레드 사용을 우선시하세요
물론 소위 대규모 계산은 CPU를 많이 소모하고 자주 전환하는 경우에는 스레드가 가장 적합합니다.
이 원리는 이미지 처리 및 알고리즘 처리에 가장 일반적으로 사용됩니다.
3) 강한 상관 처리에는 스레드가 사용되고, 약한 상관 처리에는 프로세스가 사용됩니다.
강 상관과 약한 상관이란 무엇인가요? 이론상으로는 정의하기 어렵지만 간단한 예를 들어보면 이해할 수 있다.
일반 서버는 메시지 송수신, 메시지 처리 등의 작업을 완료해야 합니다. "메시지 전송 및 수신"과 "메시지 처리"는 관련성이 낮은 작업이고 "메시지 처리"는 "메시지 디코딩"과 "비즈니스 처리"로 나눌 수 있으며 이 두 작업은 상대적으로 훨씬 더 밀접하게 관련되어 있습니다. 따라서 "메시지 송수신"과 "메시지 처리"는 별도의 프로세스로 설계할 수 있고, "메시지 디코딩"과 "비즈니스 처리"는 별도의 스레드로 설계할 수 있습니다.
물론 이 분할 방식은 고정적이지 않으며 실제 상황에 따라 조정될 수도 있습니다.
4) 여러 머신에 분산된 프로세스와 멀티 코어에 분산된 스레드를 사용하도록 확장될 수 있습니다.
이유는 위의 비교를 참조하세요.
5) 모든 요구 사항이 충족되면 가장 익숙하고 가장 잘하는 방법을 사용하십시오.
소위 "데이터 공유, 동기화", "프로그래밍, 디버깅" 및 "신뢰성" 차원에 대해서는 어떻게 "복잡성과 단순성" 중에서 선택하려면 선택할 수 있는 명확한 방법이 없다고 말할 수 있습니다. 하지만 선택 원칙은 말씀드릴 수 있습니다. 멀티 프로세싱과 멀티스레딩이 모두 요구 사항을 충족할 수 있다면 가장 익숙하고 가장 잘하는 것을 선택하세요.
주의해야 할 점은 제가 너무 많은 선택 원칙을 제시했지만 실제 적용은 기본적으로 "프로세스 + 스레드"의 조합이라는 것입니다.
자원 소비:
커널의 관점에서 프로세스의 목적은 시스템 자원(CPU 시간, 메모리 등)을 할당하기 위한 기본 단위 역할을 하는 것입니다. 스레드(Thread)는 프로세스의 실행 스트림으로, CPU 스케줄링 및 디스패치의 기본 단위로, 프로세스보다 작고 독립적으로 실행될 수 있는 기본 단위이다.
스레드는 서로 동일한 주소 공간을 사용하고 대부분의 데이터를 공유합니다. 스레드를 시작하는 데 소요되는 공간은 프로세스를 시작하는 데 소요되는 공간보다 훨씬 적습니다. 프로세스를 시작하는 데 걸리는 시간입니다. 통계에 따르면 일반적으로 프로세스의 오버헤드는 스레드의 오버헤드보다 약 30배입니다. 물론 특정 시스템에서는 이 데이터가 크게 다를 수 있습니다.
통신 방법:
프로세스 간 데이터를 전송하는 유일한 방법은 통신을 통해서만 이루어지므로 시간이 많이 걸리고 불편합니다. 대부분의 스레드 시간 데이터는 공유되므로(스레드 함수 내에서는 공유되지 않음) 빠르고 편리합니다. 그러나 데이터 동기화에는 잠금이 필요하며 정적 변수에 특별한 주의를 기울여야 합니다.
스레드 고유의 장점:
다중 CPU 시스템을 더욱 효율적으로 만드는 애플리케이션 응답 향상. 운영 체제는 스레드 수가 CPU 수보다 크지 않은 경우 다른 스레드가 다른 CPU에서 실행되도록 보장합니다.
프로그램 구조를 개선합니다. 길고 복잡한 프로세스는 여러 스레드로 나누어 여러 개의 독립적이거나 반독립적인 실행 부분이 될 수 있습니다. 이러한 프로그램은 이해하고 수정하기가 더 쉽습니다.
/** * 入口函数 * 将此文件保存为 ProcessOpera.php * 在terminal中运行 /usr/local/php/bin/php ProcessOpera.php & * 查看进程 ps aux|grep php */ ProcessOpera("runCode", array(), 8); /** * run Code */ function runCode($opt = array()) { //需要在守护进程中运行的代码 } /** * $func为子进程执行具体事物的函数名称 * $opt为$func的参数 数组形式 * $pNum 为fork的子进程数量 */ function ProcessOpera($func, $opts = array(), $pNum = 1) { while(true) { $pid = pcntl_fork(); if($pid == -1) { exit("pid fork error"); } if($pid) { static $execute = 0; $execute++; if($execute >= $pNum) { pcntl_wait($status); $execute--; } } else { while(true) { //somecode $func($opts); sleep(1); } exit(0); } } }
class My extends Thread { protected $name; public $runing; function __construct($name){ $this->runing=1; $this->param=0; $this->name=$name; } public function run() { while($this->runing){ if($this->param){ $time=rand(1,5); echo 'I am thread '.$this->name.',pid: '.$this->getCreatorId().",param: {$this->param},need {$time}s\n"; sleep($time); $this->param=0; }else{ echo "Thread {$this->name} waiting...\n"; } sleep(1); } } } $pool=array(); $pool[]=new My('a'); $pool[]=new My('b'); $pool[]=new My('c'); //开启所有线程 foreach ($pool as $w) { $w->start(); } //派发任务 unset($w); for($i=1;$i<10;$i++){ $woker_content=$i; while(1){ foreach($pool as $w){ if(!$w->param){ $w->param=$woker_content; echo "Thread {$w->name} empty,put param {$woker_content}.\n"; break 2; } } sleep(1); } } unset($w); while(count($pool)){ foreach ($pool as $k => $w) { if(!$w->param){ $w->runing=false; unset($pool[$k]); echo "Thread {$w->name} end,exit!\n"; } } sleep(1); } echo 'All thread end!';
관련 권장 사항:
자세한 설명 PHP 방식으로 예약된 작업을 구현하는 다섯 가지 방법
위 내용은 PHP는 다중 프로세스 및 다중 스레딩을 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!