PHPでは、 xml_set_end_namespace_decl_handlerを使用して、XMLパーサーにコールバックを設定します。この関数は、主にXML_PARSER_CREATEを使用して作成されたパーサーなど、イベントベースのXML解析に使用されます。
ただし、PHPの拡張機能のほとんど(XML拡張機能を含む)のほとんどがスレッドセーフ(NTS)ではなく、パーサーインスタンス、コールバック関数、またはコールバック関数、または直接人種条件、記憶腐敗、または予期しない行動を引き起こす可能性があるため、マルチスレッド環境(PTHREADSまたは同時リクエストの使用など)では、スレッドセーフ(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";
});
コールバックでグローバル$ 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やスタンドアロンプロセスプールの使用など)の使用を検討してください。