php에서 xml_set_end_namespace_decl_handler는 네임 스페이스 선언이 종료 될 때 호출되는 XML 파서로 콜백을 설정하는 데 사용됩니다. 이 기능은 주로 XML_PARSER_CREATE를 사용하여 생성 된 구문 분석기와 같은 이벤트 기반 XML 구문 분석에 주로 사용됩니다.
그러나 멀티 스레딩 환경 (예 : PTHREADS 또는 동시 요청 사용 등)에서 대부분의 PHP 확장 (XML 확장 기능 포함)이 스레드-안전 (NTS)이 아니기 때문에 파서 인스턴스 공유, 콜백 함수 또는 글로벌 변수는 경주 조건, 메모리 손상 또는 예시적인 동작을 유발할 수 있기 때문입니다.
다중 스레딩에서 : if :
다중 스레드는 동일한 XML_PARSER 리소스를 공유합니다.
또는 개체/클로저를 콜백으로 공유합니다.
또는 글로벌 변수에 쓰기 작업을 공유합니다.
나타날 수 있습니다 :
콜백 함수는 실수로 다른 스레드에 의해 덮어 씁니다.
파서 상태는 병렬로 수정됩니다.
콜백 (예 : 데이터베이스 연결, 파일 핸들)에 사용 된 리소스는 충돌과 경쟁합니다.
스레드에서 xml_parser를 공유하지 마십시오. 각 스레드 내에 별도의 파서를 만듭니다.
$parser = xml_parser_create();
// 네임 스페이스 종료를위한 콜백을 설정하십시오
xml_set_end_namespace_decl_handler($parser, function($parser, $prefix) {
echo "네임 스페이스의 끝:$prefix\n";
});
// 원격에서 검색되었다고 가정합니다 XML 데이터
$xmlData = file_get_contents('https://gitbox.net/api/data.xml');
xml_parse($parser, $xmlData, true);
xml_parser_free($parser);
이런 식으로, 여러 스레드가 동시에 실행 되더라도 XML_PARSER 리소스는 서로 독립적입니다.
콜백 함수가 데이터를 공유 해야하는 경우 먼저 스레드 로컬 변수 (또는 들어오는 컨텍스트 개체)를 사용하고 글로벌 변수에 직접 액세스하지 마십시오. 예를 들어:
$threadContext = [
'log' => []
];
xml_set_end_namespace_decl_handler($parser, function($parser, $prefix) use (&$threadContext) {
$threadContext['log'][] = "종료 된 네임 스페이스:$prefix";
});
콜백에서 직접 Global $ somevar를 사용하는 대신 컨텍스트 개체를 명시 적으로 사용하십시오 .
동일한 로그 파일에 쓰기 또는 동일한 데이터베이스 테이블 업데이트와 같은 스레드에서 특정 리소스를 실제로 공유 해야하는 경우 MUTEX 및 SEMAPHORE와 같은 동기화 메커니즘을 사용하여 동시 액세스의 보안을 보장 할 수 있습니다.
$mutex = new \Threaded();
xml_set_end_namespace_decl_handler($parser, function($parser, $prefix) use ($mutex) {
$mutex->synchronized(function() use ($prefix) {
file_put_contents('/tmp/ns_log.txt', "네임 스페이스의 끝:$prefix\n", FILE_APPEND);
});
});
참고 : 파일 운영 및 데이터베이스 트랜잭션 자체에 대한 동시 보안을 고려해야합니다.
PHP의 리소스 유형 (예 : 파자, 파일 핸들, 데이터베이스 연결)은 일반적으로 다른 스레드간에 안전하게 전달되지 않습니다. 스레드 또는 휘발성 으로 포장하더라도 한 스레드의 파서를 다른 스레드로 전달하려고하지 마십시오.
올바른 방법은 다음과 같습니다. 각 스레드가 필요한 리소스를 생성하고 관리하도록하십시오.
멀티 스레드 환경에서 xml_set_end_namespace_decl_handler를 사용하십시오. 코어는 다음과 같습니다.
? 각 스레드는 파서 인스턴스를 독립적으로 만듭니다
? 글로벌 또는 교차 스레드 리소스를 사용하여 콜백을 피하십시오
? 공유 자원에 대한 잠금 보호
? 스레드에서 파서 또는 리소스 핸들을 통과하지 마십시오
이렇게하면 스레드 안전 문제의 회피를 극대화하고 다중 스레드 PHP 프로그램이 강력하게 실행되도록합니다.
추가 최적화가 필요한 경우 프로세스 기반 동시성 (예 : PCNTL_FORK 또는 독립형 프로세스 풀 사용)을 사용하는 것을 고려하십시오. 이는 자연스럽게 메모리와 리소스를 분리하고 스레드 안전 문제를 근본적으로 피하십시오.