2011-03-04 10 views
1

すべてのスレッドはメモリロケーションを共有します。たとえば、あるスレッドでグローバル変数を変更すると、別のスレッドに反映されます。各スレッドには独自のスタックがあるため、スレッド内で作成されるローカルの 変数は一意です。この場合、スレッド固有のデータメカニズムのためには、なぜ が必要ですか?自動ストレージの可変機能で実現できない スレッド機能の中に?pthreadにスレッド固有のデータが必要なのはなぜですか?

わかりやすく!!!

BR Rjの

+0

すべてのグローバル変数は、デフォルトですべてのスレッド間で共有されます。 IIRCでは、スレッド固有のデータを使用して、変数が同じ名前でスレッド固有の変数を指定することもできます。 – Kakira

答えて

0

はい、スタックは、(特定のスレッドに対してローカル割り当てをヒープにハンドルを含む)スレッドローカルストレージを割り当てる1つの方法です。

3

通常のグローバルはスレッド間で共有されます。ローカル変数は、関数の特定の呼び出しに固有です。同じスレッドで動作しているが、そのスレッドに固有のいくつかの機能が(たとえば)見えるようにするには、スレッド固有のデータが必要です。

1

が必要です。ですが、それはかなり便利です。 randおよびstrtokのような一部の機能は、スレッド間で共有するときに問題になる可能性がある静的記憶期間情報を使用します。

スレッドごとに異なるシーケンス(したがってシード)を維持したいと思う乱数関数があるとします。あなたには2つのアプローチがあります。

あなたは場しのぎのようなものを使用することができます。シードは持って

int seed; 
srand (&seed, time (NULL)); 
int r = rand_r (void *seed); 

は、発信者によって作成され、各時間に渡されます。

それとも、むしろよりよい、ISO準拠を使用することができます:スレッド固有種を維持するために、スレッドローカルストレージを使用しています

srand (time (NULL)); 
int r = rand(); 

。同様に、文字列内の位置に関して処理されているstrtokの情報と同様です。

こうして、スレッド化されたバージョンとスレッド化されていないバージョンの間でコードを変更する必要はありません。

この情報をスレッド関数で作成することはできますが、rand関数はその情報を渡すことなくそのアドレスを知ることができます。そしてrandが87のスタック・レベルダウンと呼ばれるとどうなりますか?これは、ポインタを転送するために非常に多くのレベルです。あなたが何かを行う場合でも

そして、:

void pthread_fn (void *unused) { 
    int seed; 
    rand_set_seed_location (&seed); 
    : 
} 

randはその後、それはまだ標準からのコードの変更ですが、関係なく、それがスタックにあるどのように深いの値を使用しています。それは動作するかもしれませんが、COBOLにオペレーティングシステムを書くかもしれません。つまり、

0

スレッド固有のデータの最良の例:-)良いアイデア「errnoに」であることはありません。cライブラリの関数への呼び出しに失敗した場合、errnoが設定されています。これを調べて、失敗の理由を調べることができます。スレッド固有のデータがない場合は、エラー番号をチェックする前に他のスレッドによって設定される可能性があるため、これらの関数をマルチスレッド環境に移植することは不可能です。

+0

しかし、どのようにスレッド固有のデータにerrnoを保持していますか? – user504542

+0

glibcのerrnoはスレッド固有のデータで実装されているため、競合については心配しないでください。 – burningice

0

一般に、新しいAPIではTSDのほとんどの使用を避けるべきです。関数が何らかの情報を必要とする場合は、関数に渡す必要があります。

ただし、TSDがAPIの不具合を「ペーパーオーバー」する必要があることがあります。良い例は 'gmtime'です。 'gmtime'関数は、次回の 'gmtime'呼び出しまで有効な構造体へのポインタを返します。しかし、それはマルチスレッドプログラムでは非常に使いにくいものになるでしょう。あなたがそれを期待していないときにあなたの構造を壊すいくつかの図書館が「gmtime」と呼ばれたら? 1つの簡単な回避策は、構造体をスレッド固有に戻すことです。 (もちろん、長期的な解決策は「gmtime_r」などのより適切なAPIを作成することです)

新しいデザインでTSDを使用するのが完全に合理的な1つのケースは、頻繁にアクセスされない情報それはAPIを混乱させるでしょう。たとえば、重大なエラーが検出された場合、上位レベルのコードから特定のコンテキスト情報をログに記録するとよいでしょう(どのクライアントがサービスしていましたか、どのコマンドを送信しましたか)。基本的には、このコンテキスト情報を関数から関数に(関数の一部があなたのコントロールの外にある場合は常に可能ではない)渡すか、それをTSDに格納することです。

関連する問題