3

各スレッドには独自のスタックがあるため、そのプライベート データをそこに置くことができます。たとえば、各スレッドはヒープ メモリを割り当ててデータ構造を保持し、同じインターフェイスを使用してそれを操作できます。では、なぜスレッド固有のデータが役立つのでしょうか?

私が考えることができる唯一のケースは、各スレッドが多くの種類のプライベート データを持つ可能性があるということです。そのスレッド内で呼び出される関数のプライベート データにアクセスする必要がある場合、データを引数としてそれらすべての関数に渡す必要がありますが、これは退屈でエラーが発生しやすいものです。

4

8 に答える 8

4

スレッド ローカル ストレージは、グローバル状態を回避するためのソリューションです。データがスレッド間で共有されていないが、複数の関数によってアクセスされる場合は、スレッド ローカルにすることができます。再入可能性を壊す心配はありません。デバッグがはるかに簡単になります。

パフォーマンスの観点から見ると、スレッド ローカル データを使用することは、偽共有を回避する方法です。2 つのスレッドがあり、1 つは変数xへの書き込みを担当し、もう 1 つは変数yからの読み取りを担当するとします。これらをグローバル変数として定義する場合、それらは同じキャッシュ ライン上にある可能性があります。これは、スレッドの 1 つがxに書き込むと、CPU がキャッシュ ラインを更新することを意味します。これにはもちろん変数yが含まれます。したがって、 yを更新する理由がないため、キャッシュのパフォーマンスが低下します。

スレッド ローカル データを使用した場合、1 つのスレッドは変数xのみを格納し、もう 1 つのスレッドは変数yのみを格納するため、誤った共有が回避されます。ただし、キャッシュ ラインのパディングなど、他の方法もあることに注意してください。

于 2012-06-19T13:11:43.663 に答える
2

スレッド ローカル ストレージは、別の種類のグローバル変数と考えてください。渡す必要がないという意味でグローバルであり、さまざまなコードが好きなようにアクセスできます(もちろん宣言があれば)。ただし、スレッドごとに個別の変数があります。通常、マルチスレッド プログラミングでは、他のスレッドが値を変更する可能性があるため、グローバルは非常に不適切です。スレッド ローカルにすると、自分のスレッドだけがそれを見ることができるので、別のスレッドが予期せず変更することはありません。

もう 1 つの使用例は、コールバック関数に情報を運ぶためにグローバル変数を使用することを期待する (不適切に設計された) API を使用せざるを得ない場合です。これはグローバル変数に強制される単純な例ですが、スレッド ローカル ストレージを使用してスレッド セーフにしています。

于 2012-06-19T12:47:49.077 に答える
2

ええと、私は 30 年ほどマルチスレッド アプリを書いてきましたが、TLS を使用する必要性をまったく感じたことはありません。DB がスレッドにバインドする DB 接続がスレッドに必要な場合、スレッドは独自の接続を開き、それをスタックに保持できます。スレッドは呼び出すことができず、シグナルを送るだけなので問題ありません。この魔法の「TLS」を見るたびに、それが私の問題の解決策ではないことに気づきました。

オブジェクトが決して終了しないスレッドのキューに入れられる私の典型的なメッセージ パッシング設計では、TLS はまったく必要ありません。

スレッドプールを使用すると、さらに役に立たなくなります。

TLSの使用=悪い設計としか言えません。できれば、誰かが私を正してください:)

于 2012-06-19T13:11:31.200 に答える
2

スタック (スレッド ローカル データが各スレッド専用であるのと同様) とは異なり、スレッド ローカル データは、関数呼び出しを通じて持続するため便利です (関数外で使用された場合に既に上書きされる可能性があるスタック データとは異なります)。

別の方法として、各スレッド専用の隣接するグローバル データを使用することもできますが、CPU キャッシュが関係している場合、パフォーマンスに影響があります。異なるスレッドは異なるコアで実行される可能性が高いため、このようなグローバルなデータの「共有」は、望ましくないパフォーマンスの低下をもたらす可能性があります。これは、あるコアからのアクセスが別のコアのキャッシュラインを無効にする可能性があるためです。キャッシュの一貫性を確保するためのコア トラフィック。

対照的に、スレッド ローカル データの操作は、概念的には、他のコアのキャッシュを台無しにする必要はありません。

于 2012-06-19T12:30:31.530 に答える
0

スレッド固有データは、特定のスレッドのすべての関数が 1 つの共通変数にアクセスする必要がある場合に使用されます。この変数は、その特定のスレッドに対してローカルですが、そのスレッドのすべての関数に対してグローバル変数として機能します。

任意のプロセスの 2 つのスレッド t1 と t2 があるとします。変数「a」は、t1 のスレッド固有のデータです。次に、t2 は 'a' に関する知識はありませんが、t1 のすべての関数はグローバル変数として 'a' にアクセスできます。「a」の変更は、t1 のすべての関数によって認識されます。

于 2015-03-02T09:06:27.173 に答える
0

データベース接続と、場合によっては要求/応答オブジェクトにスレッド ローカル ストレージを使用しました。2 つの例を挙げると、どちらも Java webapp 環境からのものですが、原則は保持されます。

Web アプリは、さまざまなサブシステムを呼び出す大量のコードで構成されている場合があります。これらの多くは、データベースにアクセスする必要がある場合があります。私の場合、db が db プールから db 接続を取得し、接続を使用し、接続をプールに返す必要がある各サブシステムを作成しました。スレッド ローカル ストレージは、より単純な代替手段を提供します。リクエストが作成されると、プールからデータベース接続をフェッチし、それをスレッド ローカル ストレージに格納します。各サブシステムは、スレッド ローカル ストレージからの db 接続を使用するだけで、リクエストが完了すると、接続を db プールに返します。このソリューションにはパフォーマンス上の利点がありましたが、データベース接続をすべてのレベルに渡す必要もありませんでした。つまり、パラメーター リストは短くなりました。

同じ Web アプリで、1 つのリモート サブシステムで、Web Request オブジェクトを実際に表示することにしました。そのため、このオブジェクトを最後まで渡すようにリファクタリングする必要がありましたが、これには多くのパラメーターの受け渡しとリファクタリングが必要でした。または、単にオブジェクトをスレッド ローカル ストレージに配置して、必要なときに取得することもできました。

どちらの場合も、そもそも設計を台無しにして、ベーコンを保存するために Thread Local ストレージを使用しただけだと主張することができます。あなたはポイントを持っているかもしれません。しかし、スレッド ローカルは、スレッド セーフを維持しながら、よりクリーンなコードを作成したと主張することもできます。

もちろん、スレッド ローカルに入れているものが実際にスレッドごとに 1 つだけであることを十分に確認する必要がありました。Web アプリの場合、Request オブジェクトまたはデータベース接続がこの説明にうまく適合します。

于 2012-06-19T12:22:52.057 に答える
0

上記の回答に追加したいのですが、私の知る限り、パフォーマンスに関しては、スタックへの割り当てはヒープへの割り当てよりも高速です。

呼び出し間でローカルデータを渡すことに関しては、ヒープに割り当てる場合は、ポインター/参照を渡す必要があります (私はJavaの男です:))呼び出しに-そうでない場合、どのようにメモリにアクセスしますか?

TLS は、スレッド内の呼び出し間でデータを渡すためのコンテキストを保存するためにも適しています (スレッド全体でログオンしているユーザーに関する情報を保持するために使用します - ある種のセッション管理)。

于 2012-06-19T15:47:06.867 に答える