ホームページ  >  記事  >  バックエンド開発  >  PHP と Zend Engine のスレッド セーフティ モデルの詳細な学習_PHP チュートリアル

PHP と Zend Engine のスレッド セーフティ モデルの詳細な学習_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-21 14:58:25858ブラウズ

PHP ソース コードを読み、PHP 拡張機能の開発を学ぶ過程で、「TSRM」という単語を含む多数のマクロに遭遇しました。情報を調べた結果、これらのマクロが Zend のスレッド セーフティ メカニズムに関連していることがわかりました。ほとんどの情報では、これらのマクロの特定の機能については説明せず、確立されたルールに従ってこれらのマクロを使用することを推奨しています。何が起こっているのかわからないのはいつも不安なので、ソースコードを読み、限られた情報を参照して関連するメカニズムを簡単に理解しました。この記事は私の研究内容を要約したものです。
この記事では、まず PHP におけるスレッド セーフティの概念とスレッド セーフティの背景について説明し、次に PHP のスレッド セーフティ メカニズム ZTS (Zend Thread Safety) と TSRM の具体的な実装について詳細に調査します。調査内容には関連するデータ構造が含まれます。 、実装の詳細と動作メカニズムについて説明し、最後にシングルスレッド環境とマルチスレッド環境における Zend の選択的コンパイルの問題について検討しました。

スレッドセーフ

スレッド セーフの問題は、一言で言えば、マルチスレッド環境でパブリック リソースに安全にアクセスする方法です。各スレッドはプライベート スタックのみを持ち、それが属するプロセスのヒープを共有することがわかっています。 C では、関数の外で変数を宣言すると、その変数はプロセスの共有記憶領域に割り当てられるため、スレッドが変更すると、その変数はプロセスの共有記憶領域に割り当てられます。この変数が設定されている場合、すべてのスレッドに影響します。これはスレッドがデータを共有するのに便利であるように見えますが、PHP はスレッドごとに 1 つのリクエストを処理することが多いため、各スレッドがグローバル変数のコピーを持つことが望まれ、リクエストが相互に干渉することは望ましくありません。

初期の PHP はシングルスレッド環境で使用されることが多かったので、各プロセスは 1 つのスレッドのみを開始したため、スレッドの安全性の問題はありませんでした。その後、マルチスレッド環境での PHP の使用が登場したため、Zend はスレッドの安全性を確保するために Zend Thread Safety (ZTS) メカニズムを導入しました。

ZTSの基本原則と実装

基本的な考え方

そういえば、ZTS の基本的な考え方は、各グローバル変数が各スレッドにコピーを持つ必要があるという意味ではないでしょうか?次に、このメカニズムを提供します:

マルチスレッド環境では、グローバル変数の適用は単に変数を宣言するだけではなく、プロセス全体が「スレッド グローバル変数プール」としてヒープ上にメモリ領域を割り当てます。このメモリ プールは初期化されます。スレッドがグローバル変数を適用する必要があるときはいつでも、プロセスが開始され、対応するメソッドを通じて TSRM (Thread Safe Resource Manager、ZTS の特定の実装) が呼び出され、必要なパラメータ (変数サイズなど) が渡されます。 ) TSRM は、メモリ プール内の対応するメモリ ブロックを割り当て、これを格納する役割を果たします。これにより、次回このスレッドがこの変数の読み取りまたは書き込みが必要になったときに、一意の参照を渡すことができます。 ID を TSRM に送信し、TSRM が実際の読み取りおよび書き込み操作を担当します。これにより、スレッドセーフなグローバル変数が実現します。以下の図は、ZTS 原理の概略図を示しています。

PHP と Zend Engine のスレッド セーフティ モデルの詳細な学習_PHP チュートリアル

Thread1 と Thread2 は同じプロセスに属しており、それぞれにグローバル変数 Global Var が必要です。TSRM はスレッドのグローバル メモリ プール (黄色の部分) 内でそれぞれに領域を割り当て、一意の ID で識別します。 2 つのスレッド 相互に干渉することなく、TSRM を介して独自の変数にアクセスできます。

Zend が特定のコード スニペットを通じてこのメカニズムをどのように実装しているかを見てみましょう。ここではPHP5.3.8のソースコードを使用しています。

TSRMの実装コードはPHPソースコードの「TSRM」ディレクトリにあります。

データ構造

TSRM には、tsrm_tls_entry と tsrm_resource_type という 2 つの重要なデータ構造があります。まず tsrm_tls_entry を見てみましょう。

tsrm_tls_entry は TSRM/TSRM.c で定義されています:

リーリー

各 tsrm_tls_entry 構造体は、スレッドのすべてのグローバル変数リソースを表す役割を果たします。ここで、thread_id はスレッド ID を格納し、count はグローバル変数の数を記録し、next は次のノードを指します。ストレージはポインターの配列として見ることができます。各要素は、このノードによって表されるスレッドを指すグローバル変数です。最後に、各スレッドの tsrm_tls_entry がリンク リスト構造に形成され、リンク リストの先頭ポインタがグローバル静的変数 tsrm_tls_table に割り当てられます。 tsrm_tls_table は実際のグローバル変数であるため、すべてのスレッドがこの変数を共有し、スレッド間のメモリ管理の一貫性が実現されることに注意してください。 tsrm_tls_entry 構造と tsrm_tls_table 構造の概略図は次のとおりです。

PHP と Zend Engine のスレッド セーフティ モデルの詳細な学習_PHP チュートリアル

tsrm_resource_type の内部構造は比較的単純です:

typedef struct {
	size_t size;
	ts_allocate_ctor ctor;
	ts_allocate_dtor dtor;
	int done;
} tsrm_resource_type;

上文说过tsrm_tls_entry是以线程为单位的(每个线程一个节点),而tsrm_resource_type以资源(或者说全局变量)为单位,每次一个新的资源被分配时,就会创建一个tsrm_resource_type。所有tsrm_resource_type以数组(线性表)的方式组成tsrm_resource_table,其下标就是这个资源的ID。每个tsrm_resource_type存储了此资源的大小和构造、析构方法指针。某种程度上,tsrm_resource_table可以看做是一个哈希表,key是资源ID,value是tsrm_resource_type结构。

精彩内容,请点击下一页!

  • 共4页:
  • 上一页
  • 1
  • 2
  • 3
  • 4
  • 下一页

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/363868.htmlTechArticle在阅读PHP源码和学习PHP扩展开发的过程中,我接触到大量含有TSRM字眼的宏。通过查阅资料,知道这些宏与Zend的线程安全机制有关,而绝大...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。