이 PECL 패키지가 threads라는 것을 발견 했지만 아직 릴리스가 없습니다. 그리고 PHP 웹 사이트에는 아무것도 나오지 않습니다.
답변
내가 아는 것이 없습니다. 다음으로 가장 좋은 방법은 CLI를 통해 한 스크립트가 다른 스크립트를 실행하도록하는 것이지만 약간 기초적인 내용입니다. 당신이하려는 일과 그것이 얼마나 복잡한 지에 따라, 이것은 옵션 일 수도 있고 아닐 수도 있습니다.
답변
pthreads 확장에 대한 PHP 매뉴얼에서 :
pthreads는 PHP에서 사용자 랜드 멀티 스레딩을 허용하는 객체 지향 API입니다. 웹 또는 콘솔을 대상으로하는 멀티 스레드 응용 프로그램을 만드는 데 필요한 모든 도구가 포함되어 있습니다. PHP 애플리케이션은 스레드, 워커 및 스택 어블을 생성, 읽기, 쓰기, 실행 및 동기화 할 수 있습니다.
이것이 들리는 것처럼, 그것은 사실입니다. 오늘날, PHP는 그것을 시도하려는 사람들을 위해 멀티 스레드를 할 수 있습니다.
PHP4의 첫 번째 릴리스 인 2000 년 5 월 22 일, PHP는 스레드 안전 아키텍처와 함께 제공되어 멀티 스레드 SAPI (Server API) 환경에서 별도의 스레드로 여러 인터프리터의 인터프리터 인스턴스를 실행할 수 있습니다. 지난 13 년 동안이 아키텍처의 디자인은 유지되고 발전되었습니다. 그 이후로 세계에서 가장 큰 웹 사이트에서 프로덕션으로 사용되었습니다.
사용자 영역에서의 스레딩은 PHP 팀에게는 전혀 관심이 없었으며 오늘날에도 마찬가지입니다. PHP가 비즈니스를 수행하는 세계에는 이미 하드웨어 확장이라는 정의 된 확장 방법이 있다는 것을 이해해야합니다. 수년 동안 PHP가 존재하고 하드웨어는 저렴하고 저렴 해졌으며 이는 PHP 팀의 관심사가 점점 줄어 들었습니다. 저렴 해지면서 훨씬 강력 해졌습니다. 오늘날 우리의 휴대 전화 및 태블릿에는 듀얼 및 쿼드 코어 아키텍처와 많은 RAM이 있으며, 데스크탑 및 서버에는 일반적으로 8 또는 16 코어, 16 및 32 기가 바이트 RAM이 있지만 항상 2 개를 가질 수는 없습니다. 예산 내에서 두 대의 데스크톱을 사용하는 것이 우리에게는 거의 유용하지 않습니다.
또한 PHP는 프로그래머가 아닌 사람들을 위해 작성되었으며 많은 애호가들이 모국어입니다. PHP가 그렇게 쉽게 채택되는 이유는 배우고 쓰기가 쉬운 언어이기 때문입니다. 오늘날 PHP가 신뢰할 수있는 이유는 디자인에 들어가는 방대한 양의 작업과 PHP 그룹의 모든 단일 결정 때문입니다. 몇 년이 지난 후에도 신뢰성과 굉장한 위대함이 스포트라이트를 유지합니다. 라이벌이 시간이나 압력에 빠진 곳.
멀티 스레드 프로그래밍은 가장 일관성 있고 안정적인 API를 사용하더라도 생각해야 할 사항이 많으며 많은 오해가 있습니다. PHP 그룹은 사용자 랜드 멀티 스레딩이 핵심 기능이되기를 원하지 않습니다. 심각한 관심을받지 못했습니다. PHP는 모두에게 복잡하지 않아야합니다.
고려해야 할 모든 것, PHP가 프로덕션 준비 및 테스트 된 기능을 활용하여 우리가 가진 것을 최대한 활용할 수있는 수단을 제공함으로써 더 많은 것을 추가하는 것이 항상 옵션이 아니며 많은 경우 여전히 이점이 있습니다. 작업이 실제로 필요하지 않습니다.
pthreads는 사용자가 그것을 탐색하고자하는 사람들을 위해 사용자가 PHP 응용 프로그램을 멀티 스레딩 할 수있는 API를 달성합니다. API는 매우 진행중인 작업이며 베타 수준의 안정성과 완전성을 지정했습니다.
PHP가 사용하는 라이브러리 중 일부는 스레드로부터 안전하지 않다는 것은 일반적인 지식입니다. pthreads가이를 변경할 수 없으며 시도하지 않음을 프로그래머에게 분명히 알려야합니다. 그러나 인터프리터의 다른 스레드 안전 설정에서와 같이 스레드 안전 라이브러리를 사용할 수 있습니다.
pthreads는 Posix Threads (Windows에서도)를 사용합니다. 프로그래머가 만드는 것은 실제 실행 스레드이지만, 스레드가 유용하려면 PHP를 알아야 사용자 코드를 실행하고 변수를 공유하며 유용한 통신 수단을 사용할 수 있습니다 (동기화). 따라서 모든 스레드는 인터프리터 인스턴스로 작성되지만 설계 상 인터프리터는 멀티 스레드 서버 API 환경과 마찬가지로 인터프리터의 다른 모든 인스턴스와 분리되어 있습니다. pthreads는 깔끔하고 안전한 방식으로 격차를 해소하려고합니다. C의 스레드 프로그래머에 대한 많은 우려는 pthreads 프로그래머에게는 존재하지 않습니다. 설계 상 pthreads는 읽기시 복사 및 쓰기시 복사 (RAM은 저렴합니다), 따라서 두 인스턴스가 동일한 물리적 데이터를 조작하지 않습니다. 하지만 다른 스레드의 데이터에 영향을 줄 수 있습니다.
읽기에서 복사하고 쓰기에서 복사하는 이유 :
public function run() {
...
(1) $this->data = $data;
...
(2) $this->other = someOperation($this->data);
...
}
(3) echo preg_match($pattern, $replace, $thread->data);
(1) pthreads 객체 데이터 저장소에서 읽기 및 쓰기 잠금이 유지되는 동안 데이터는 메모리의 원래 위치에서 객체 저장소로 복사됩니다. pthreads는 변수의 참조 횟수를 조정하지 않으므로 Zend는 더 이상 참조가 없으면 원래 데이터를 해제 할 수 있습니다.
(2) someOperation에 대한 인수는 (1) 결과의 사본 자체가 엔진에 대해 zval 컨테이너로 다시 복사되는 저장된 원래 데이터 인 오브젝트 저장소를 참조합니다.이 경우 읽기 잠금이 유지됩니다. 오브젝트 저장소, 잠금이 해제되고 엔진이 기능을 실행할 수 있습니다. zval이 작성되면 참조 횟수는 0이며, 참조가 존재하지 않기 때문에 엔진이 조작 완료시 사본을 해제 할 수 있습니다.
(3) preg_match의 마지막 인수는 데이터 저장소를 참조하고, 읽기 잠금이 획득되고, (1)에 설정된 데이터가 다시 0의 참조 횟수로 zval에 복사됩니다. 잠금이 해제되고 preg_match에 대한 호출은 다음에서 작동합니다. 데이터 사본, 즉 그 자체가 원본 데이터의 사본.
알아야 할 사항 :
-
스레드 안전 데이터가 저장되는 오브젝트 저장소의 해시 테이블은
Zend가 PHP와 함께 제공 한 TsHashTable을 기반으로합니다. -
오브젝트 저장소에는 읽기 및 쓰기 잠금이 있으며, TsHashTable에 대한 추가 액세스 잠금이 제공되므로 필요한 경우 (var_dump / print_r, PHP 엔진이 참조하고자하는 속성에 직접 액세스) pthread가 TsHashTable을 조작 할 수 있습니다. 정의 된 API 외부.
-
잠금은 복사가 수행되는 동안, 사본이 만들어 졌을 때 잠금이 해제 된 상태에서 합리적인 순서로만 유지됩니다.
이것은 다음을 의미합니다.
-
쓰기가 발생하면 읽기 및 쓰기 잠금뿐만 아니라 추가 액세스 잠금이 유지됩니다. 테이블 자체가 잠겨 있으므로 다른 컨텍스트가 잠금, 읽기, 쓰기 또는 영향을 줄 수있는 방법이 없습니다.
-
읽기가 발생하면 읽기 잠금이 유지 될뿐만 아니라 추가 액세스 잠금도 다시 테이블이 잠 깁니다.
두 컨텍스트가 오브젝트 저장소에서 동일한 데이터에 물리적으로 또는 동시에 액세스 할 수는 없지만 참조를 사용하여 컨텍스트에서 작성된 쓰기는 참조가있는 컨텍스트에서 읽은 데이터에 영향을줍니다.
이것은 아무 것도 공유하지 않으며 존재하는 유일한 방법은 공존합니다. 약간 정통한 사람들은 여기에 많은 복사가 진행되고 있으며 이것이 좋은지 궁금해 할 것입니다. 다이나믹 런타임에서 상당히 많은 복사가 진행됩니다. 다이나믹 언어의 다이나믹입니다. pthreads는 객체의 수준에서 구현됩니다. 하나의 객체를 제대로 제어 할 수는 있지만 메소드 (프로그래머가 실행하는 코드)에는 잠금 및 복사가없는 다른 컨텍스트가 있으며 로컬 메소드 범위가 있습니다. pthreads 객체의 경우 객체 범위는 컨텍스트간에 데이터를 공유하는 방법으로 취급되어야합니다. 이를 염두에두고 필요한 경우가 아니라면 객체 저장소를 잠그지 않는 기술을 채택 할 수 있습니다.
PHP에 사용할 수있는 대부분의 라이브러리와 확장 프로그램은 타사를 중심으로하는 씬 래퍼이며 PHP 핵심 기능은 어느 정도 동일합니다. pthreads는 Posix Threads의 얇은 래퍼가 아닙니다. Posix Threads를 기반으로 한 스레딩 API입니다. PHP에서 스레드를 구현할 때 사용자가 이해하지 못하거나 사용할 수 없다는 점은 없습니다. 뮤텍스가 무엇인지 모르는 사람이 기술과 자원 측면에서 자신이 가진 모든 것을 이용할 수 없어야 할 이유는 없습니다. 객체는 객체처럼 작동하지만 두 컨텍스트가 충돌 할 때마다 pthread는 안정성과 안전성을 제공합니다.
자바에서 일한 사람은 pthreads 객체와 자바의 스레딩 사이의 유사점을 보게 될 것입니다. 동일한 사람들은 ConcurrentModificationException이라는 오류를 보았을 것입니다. 두 개의 스레드가 동일한 물리적 데이터를 쓰면 Java 런타임에 의해 발생한 오류로 들립니다. 동시에. 나는 그것이 존재하는 이유를 이해하지만 런타임은 사용자가 안전을 얻을 수있는 정확한 시간에만 동시성을 감지 할 수 있다는 사실과 함께 저렴한 리소스로 값을 낮춰서 선택합니다. 실행 및 데이터 액세스를 관리하는 대신 런타임시 치명적인 오류가 발생합니다.
그런 바보 같은 오류는 pthreads에서 발생하지 않으며 API는 스레딩을 안정적으로 만들고 가능한 한 호환되도록 작성되었습니다.
멀티 스레딩은 새로운 데이터베이스를 사용하는 것과 다르므로 매뉴얼의 모든 단어와 pthread와 함께 제공되는 예제에주의를 기울여야합니다.
마지막으로 PHP 매뉴얼에서 :
pthreads는 꽤 좋은 결과를 얻은 실험이었습니다. 제한 사항이나 기능은 언제든지 변경 될 수 있습니다. 그것이 실험의 본질입니다. 구현에 의해 종종 부과되는 한계는 정당한 이유가 있습니다. pthreads의 목적은 모든 레벨에서 PHP의 멀티 태스킹에 유용한 솔루션을 제공하는 것입니다. pthread가 실행되는 환경에서는 안정적인 환경을 제공하기 위해 몇 가지 제한 사항이 필요합니다.
답변
다음은 Wilco가 제안한 예입니다.
$cmd = 'nohup nice -n 10 /usr/bin/php -c /path/to/php.ini -f /path/to/php/file.php action=generate var1_id=23 var2_id=35 gen_id=535 > /path/to/log/file.log & echo $!';
$pid = shell_exec($cmd);
기본적으로 이것은 명령 줄에서 PHP 스크립트를 실행하지만 즉시 PID를 반환 한 다음 백그라운드에서 실행됩니다. (echo $!는 PID 이외의 다른 것은 반환하지 않습니다.) 이렇게하면 PHP 스크립트를 계속하거나 원하는 경우 종료 할 수 있습니다. 내가 이것을 사용했을 때, 나는 사용자를 다른 페이지로 리다이렉션했다. 여기서 5-60 초마다 AJAX 호출이 수행되어 보고서가 여전히 실행 중인지 확인한다. (gen_id와 관련된 사용자를 저장하는 테이블이 있습니다.) check 스크립트는 다음을 실행합니다.
exec('ps ' . $pid , $processState);
if (count($processState) < 2) {
// less than 2 rows in the ps, therefore report is complete
}
이 기술에 대한 짧은 게시물이 여기에 있습니다 : http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/
답변
요컨대, php에는 멀티 스레딩이 있지만 대신 멀티 프로세싱을 사용해야합니다.
Backgroud 정보 : 스레드와 프로세스
스레드와 프로세스의 구별에 대해 약간의 혼란이 있기 때문에 두 가지를 간단히 설명하겠습니다.
- 스레드는 CPU가 처리 할 명령의 시퀀스이다. 그것으로 구성된 유일한 데이터는 프로그램 카운터입니다. 각 CPU 코어는 한 번에 하나의 스레드 만 처리하지만 스케줄링을 통해 다른 스레드의 실행간에 전환 할 수 있습니다.
- 프로세스가 공유 자원의 집합입니다. 즉, 메모리, 변수, 객체 인스턴스, 파일 핸들, 뮤텍스, 데이터베이스 연결 등으로 구성됩니다. 각 프로세스에는 하나 이상의 스레드가 포함됩니다. 동일한 프로세스의 모든 스레드는 리소스를 공유하므로 한 스레드에서 다른 스레드에서 변수를 사용할 수 있습니다. 해당 스레드가 서로 다른 두 프로세스의 일부인 경우 서로간에 리소스에 직접 액세스 할 수 없습니다. 이 경우 파이프, 파일, 소켓 등을 통한 프로세스 간 통신 이 필요합니다 .
멀티 프로세싱
php로 새로운 프로세스 (새로운 스레드를 포함)를 생성하여 병렬 컴퓨팅을 달성 할 수 있습니다. 스레드가 많은 통신 또는 동기화를 필요로하지 않으면 프로세스가 분리되어 서로의 작업을 방해 할 수 없으므로 선택하십시오. 하나가 충돌하더라도 다른 것은 걱정하지 않습니다. 많은 통신이 필요한 경우 프로세스 간 통신과 동기화로 인해 많은 안색이 생길 수 있으므로 “멀티 스레딩”에서 읽거나 슬프게도 다른 프로그래밍 언어를 사용해보십시오.
PHP에서는 새로운 프로세스를 생성하는 두 가지 방법이 있습니다 :
OS가 당신을 위해 그것을 할 수 있습니다 : 새 프로세스를 생성하고 새로운 (또는 동일한) 거기에 PHP 스크립트를 실행하기 위해 운영 체제를 알 수 있습니다.
-
대한 리눅스 당신은 다음을 사용하거나 고려할 수 대릴 하인의 답변을 :
$cmd = 'nice php script.php 2>&1 & echo $!'; pclose(popen($cmd, 'r'));
-
위해 창문 이를 사용할 수 있습니다 :
$cmd = 'start "processname" /MIN /belownormal cmd /c "script.php 2>&1"'; pclose(popen($cmd, 'r'));
포크로 직접 해보십시오 : PHP는 pcntl_fork () 함수를 통해 포크를 사용할 수도 있습니다 . 이 작업을 수행하는 방법에 대한 좋은 자습서는 여기 에서 찾을 수 있지만 포크는 인류 와 특히 oop 에 대한 범죄 이므로 사용하지 않는 것이 좋습니다 .
멀티 스레딩
멀티 스레딩을 사용하면 모든 스레드가 리소스를 공유하므로 많은 오버 헤드없이 쉽게 통신하고 동기화 할 수 있습니다. 다른 한편으로는 경쟁 조건과 교착 상태가 생성하기 쉽지만 디버그하기가 어렵 기 때문에 수행중인 작업을 알아야합니다.
표준 PHP는 멀티 스레딩을 제공하지 않지만 실제로는 -pthreads 를 수행하는 (실험적인) 확장명이 있습니다. API 문서도 php.net으로 만들었습니다 . 그것으로 당신은 다음 과 같이 실제 프로그래밍 언어 에서 할 수있는 일을 할 수 있습니다 🙂
class MyThread extends Thread {
public function run(){
//do something time consuming
}
}
$t = new MyThread();
if($t->start()){
while($t->isRunning()){
echo ".";
usleep(100);
}
$t->join();
}
들어 리눅스 이 설치 가이드 유래의에 바로 여기.
들어 창 이제 하나있다 :
- 먼저 스레드 안전 버전의 PHP가 필요합니다.
- pthread와 php 확장자의 미리 컴파일 된 버전이 필요합니다. 여기에서 다운로드 할 수 있습니다 . PHP 버전과 호환되는 버전을 다운로드하십시오.
- 방금 다운로드 한 zip에서 php_pthreads.dll을 php 확장 폴더 ([phpDirectory] / ext)에 복사하십시오.
- pthreadVC2.dll을 [phpDirectory] (루트 폴더-확장 폴더 아님)에 복사하십시오.
-
[phpDirectory] /php.ini를 편집하고 다음 줄을 삽입하십시오
extension=php_pthreads.dll
-
주석이있는 곳에서 잠을 자거나 위의 스크립트로 위의 스크립트로 테스트하십시오.
그리고 지금 큰 문제는 : 이것이 실제로 작동 하지만 php는 원래 멀티 스레딩을 위해 만들어지지 않았습니다. 스레드 안전 버전의 PHP가 있으며 v5.4부터는 거의 버그가없는 것으로 보이지만 멀티 스레드 환경 에서 PHP를 사용하는 것은 여전히 PHP 매뉴얼에서 권장 하지 않습니다 (그러나 아마도 매뉴얼을 업데이트하지 않았습니다) 아직). 훨씬 더 큰 문제는 많은 공통 확장이 스레드로부터 안전하지 않다는 것 입니다. 따라서이 PHP 확장명으로 스레드를 얻을 수 있지만 의존하는 기능은 여전히 스레드 안전하지 않으므로 경쟁 조건, 교착 상태 등이 발생할 수 있습니다. 코드에서 직접 작성하지 않았습니다 …
답변
pcntl_fork () 를 사용 하여 스레드와 비슷한 것을 얻을 수 있습니다 . 기술적으로는 별도의 프로세스이므로 두 스레드 간의 통신은 스레드로 간단하지 않으며 Apache가 PHP를 호출하면 작동하지 않을 것이라고 생각합니다.
답변
누군가 신경 쓰면 php_threading 을 부활 시켰 습니다. (스레드와 같지 않지만 비슷한) 실제로 그것이 ( ) 잘 작동하는 지점까지 가지고 있습니다!
답변
pcntl_fork()
당신이 찾고있는 것이지만 그 과정은 스레딩하지 않습니다. 따라서 데이터 교환에 문제가 있습니다. 그것들을 해결하기 위해 PHP 세마포어 기능을 사용할 수 있습니다 ( http://www.php.net/manual/de/ref.sem.php )을 수 있습니다. 메시지 큐는 공유 메모리 세그먼트보다 시작이 조금 더 쉽습니다.
어쨌든, 내가 개발하고있는 웹 프레임 워크에서 사용하는 전략은 웹 페이지의 리소스 집약적 블록 (아마도 외부 요청 포함)을 병렬로로드합니다. 모든 프로세스에 대한 작업을 중단하십시오. 완료되면 부모 프로세스가 액세스 할 수있는 고유 키로 데이터를 apc 캐시에 저장합니다. 모든 데이터가 있으면 계속됩니다. 간단한usleep()
아파치에서 프로세스 간 통신이 불가능하기 때문에 기다리는 것이 합니다 (어린이는 부모와의 연결을 느슨하게하고 좀비가됩니다 …). 그래서 이것은 나를 마지막으로 데려옵니다 : 모든 어린이를 스스로 죽이는 것이 중요합니다! 프로세스를 포크하지만 데이터를 유지하는 클래스도 있지만, 조사하지는 않았지만 zend 프레임 워크에는 하나가 있으며 일반적으로 느리지 만 안정적으로 코드를 작성합니다. 여기에서 찾을 수 있습니다.
http://zendframework.com/manual/1.9/en/zendx.console.process.unix.overview.html
SHM 세그먼트를 사용한다고 생각합니다! 마지막 으로이 zend 웹 사이트에 오류가 있으며 예제에서는 사소한 실수입니다.
while ($process1->isRunning() && $process2->isRunning()) {
sleep(1);
}
should of course be:
while ($process1->isRunning() || $process2->isRunning()) {
sleep(1);
}