この記事の内容は、PHP7 カーネル分析 10 のスレッド セーフについてです。必要な友人は参考にしてください。1. スレッド セーフ リソース マネージャー
PHP の SAPI のほとんどは単一です。 cli、fpm、cgi などのスレッド環境では、各プロセスは 1 つのメインスレッドのみを開始します。このモードではスレッド セーフティの問題はありませんが、Apache などのマルチスレッド環境もあり、その場合はスレッド セーフティが必要です。これは、最も一般的なものである EG や CG などのグローバル変数が多数あるため、複数のスレッドが同じ変数を共有する場合に競合するため、問題となります。そのため、PHP はマルチスレッド用のセキュリティ メカニズムを提供します。アプリケーション モデル: Zend スレッド セーフ (Zend Thread Safe、ZTS)。
PHP は、特にスレッド セーフの問題を解決するために、スレッド セーフ リソース マネージャー (TSRM) を抽象化します。実装原理は比較的単純です。リソースを共有するのは非常に難しいため、単純にリソースを共有しなければ、各スレッドは共有されなくなります。データを使用する場合、同じグローバル変数が個別にコピーされ、相互に干渉することはありません。リソースを複数のスレッドで使用する場合、事前にTSRMにリソースを登録する必要があります。その後、TSRMはリソースに一意の番号を割り当て、このリソースのサイズや初期化関数などを保存しますtsrm_resource_type 構造体。各スレッドは、TSRM によって割り当てられた番号を通じてのみこのリソースにアクセスできます。スレッドがこの番号のリソースを取得すると、それが最初のリクエストであることが判明すると、そのリソースに基づいてメモリが割り当てられます。登録時にサイズを指定してから、初期化関数を呼び出し、このリソースを初期化して、このスレッドで後で使用できるように保存します。 各スレッドには tsrm_tls_entry 構造があり、現在のスレッドのすべてのリソースはストレージ配列に保存され、添え字は各リソースの ID です。さらに、すべてのスレッドの tsrm_tls_entry 構造体が配列 tsrm_tls_table に保存されます。これはグローバル変数です。この配列内の各スレッドの tsrm_tls_entry 構造体の位置は、スレッド ID と事前に設定されたスレッド数 (tsrm_tls_table_size) をモジュロとして取得されます。複数のスレッドが tsrm_tls_table の同じ場所に格納される可能性があるため、 tsrm_tls_entry はリンク リストです。リソースを探すときは、まずスレッド ID % tsrm_tls_table_size に基づいて tsrm_tls_entry を取得し、次にリンク リストの走査を開始します。 thread_id を使用して、現在のスレッドに属しているかどうかを判断します。typedef struct { size_t size; //资源的大小 ts_allocate_ctor ctor; //初始化函数 ts_allocate_dtor dtor; int done; } tsrm_resource_type; struct _tsrm_tls_entry { void **storage; //资源数组 int count; //拥有的资源数:storage数组大小 THREAD_T thread_id; //所属线程id tsrm_tls_entry *next; };ログイン後にコピー
スレッド ローカル ストレージ (TLS)、現在のスレッドの tsrm_tls_entry を作成した後、この値は現在のスレッドの TLS に保存されるため、 ts_resource() がリソースを取得するときに、 tsrm_tls_get() を通じて直接取得でき、保存されます。ロックと取得の時間。
関連する推奨事項:
PHP7 カーネル分析 9 メモリ管理
以上がPHP7 カーネル分析 10 スレッド セーフの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。