2012-05-05 10 views
3

私は各スレッドにスレッド固有のデータを与えようとしています。これはスレッドパラメータを使用して行うことができますか?CのPOSIXスレッドローカルデータ

スレッドを作成するときに変数を渡し、スレッド関数で値を変更してスレッドごとに特定のデータとして使用しますか?

int main(void){ 
    ... 
    int Tparam = 0; 
    ... 
    rc = pthread_create(&threads[c1], NULL, Thread_Pool, (void *)Tparam); 
    ... 
} 

はその後、私はこの

void *Thread_Pool(void *param){ 
    int id; 
    id = (int) param; 
    id = value; // can this value be a specific value for this thread? 
} 
+0

pthread_keycreateなど。 – bmargulies

+3

__thread接頭辞を使用して、単にスレッドローカル変数を使用するのはなぜですか?たとえば__thread int tl_var;第2に、書き込み禁止になっている位置0を指しているので、ヌルポインタに書き込むことはできません!あなたがこれをしようとすると、セグメンテーション違反が発生します。 – MetallicPriest

+0

@bmargulies私はpthread_keycreateを読んで、これがうまくいくかどうか疑問に思いました。 – CodeRed

答えて

4

Tparamがどのように宣言されたかを示していただきありがとうございます。

しかし、各スレッドにいくつかのデータを格納するための独自の領域を持たせたい場合は、関数の引数としてその領域をスレッドに渡すことができます。たとえば、

enum { NTHREADS = 10 }; 

struct TLS_Data 
{ 
    int id; 
    char buffer[2048]; 
    size_t index; 
} data[NTHREADS]; 

for (int c1 = 0; c < NTHREADS; c1++) 
{ 
    data[c1].index = c1; 
    data[c1].id = 0; 
    data[c1].buffer[0] = '\0'; 
    int rc = pthread_create(&threads[c1], NULL, Thread_Pool, &data[c1]); 
    ...handle errors, etc... 
} 

pthread_create()の最後の引数にキャストがないことに注意してください。スコープ内にプロトタイプがある場合、ポインタをvoid *に変換する必要はありません。

Thread_Poolには、パラメータを整数として扱いたいようです。それも実行することができます。整数へのポインタを渡すことで、きれいに完了します。あなたが本当に主張する場合は、直接整数値を渡すことができますvalueのタイプはuintptr_tある

uintptr_t value = c1 + 10; 

rc = pthread_create(&threads[c1], NULL, Thread_Pool, (void *)value); 

ので、あなたはそれがボイドポインタを保持することが可能である知っている、そしてそれはあなたの作業物事の最大の機会を与えてくれます。しかし、タイプシステムと戦っているので、クリーンなコードを書くのが難しくなります。

注意すべき点の1つは、スレッド関数(例ではThread_Pool())に渡されたデータが、異なる値を参照すると見なされるスレッド間で共有されないようにする必要があることです。スレッドの実行順序の保証はありませんので、あなたのようなミスを犯した場合:

uintptr_t value = c1 + 10; 

rc = pthread_create(&threads[c1], NULL, Thread_Pool, &value); 

(およびそのコードがループしていた)、その後、どのような各スレッド機能については保証されるものではないと思いますでしょう見る。慎重にしてください!

-2

のようにそれを使用Thread_Pool機能に私はあなたの質問を理解していません。私はまだあなたが本当にやりたいことを理解できません。

いずれにせよ、私は強くサイトをチェックして、あなたをお勧めします:

彼らは短いですが、まだあなたがそうする必要がもののもののほとんどが含まれています始める。

+0

私はマルチスレッドのWebサーバーで、セマフォを持つプロデューサコンシューマアルゴリズムを使って作業しています。バッファから各FDを特定のワーカースレッドに渡して、その接続に対応できるようにしたいのです。 – CodeRed

1

pthread_self()を呼び出すことができます。それは一意のスレッドIDを返します。 juampaが推奨するLLNL URLのAPIリファレンスを参照してください。

2

この値をこのスレッドの特定の値にすることはできますか?あなたはそれを型のポインタを与える後のパラメータのポインタ間接参照する必要があり、すなわち

int id = *((int*) param); 

まあ、最初の最初の、あなたはおそらくこれが欲しいです。 void には型がないので、voidポインターを逆参照することはできません

ここで何が起こりますか?まず、スレッドを少し理解する必要があります。

まず、distinction between a thread and a process in the kernel in Linuxはありません。絶対にありません。それらはすべての実行コンテキストまたはタスクのコンテキストです。ただし、主な違いの1つは、スレッド・タスクがスレッド・スタックを除いてデータを共有することです。その答えを読んで、スレッドが作成者と他のすべてを共有していることがわかります。

スタックは共有できません。スタックは、例えばプログラムが実行可能である場合、いくつかのシステムでは値と関数のパラメータを返すなど、多くのことを追跡します。関数内で宣言された自動保存期間変数(他の修飾子を持たない変数)もスタックに格納されます。

つまり、スレッド関数内で宣言された変数は、そのスレッド固有のものです。

void threadfunc(void* param) 
{ 
    int id = /* ??? */ 
} 

スレッドの期間続くint idの独自のコピーをローカルに保存された各スレッド:だから、あなたの関数を与えられました。これを後続の関数に値で渡すか、それを指すポインタを渡すことができます。その上

int tParam[] = {1,2,3}; 

rc = pthread_create(&threads[1], NULL, Thread_Pool, (void *)&(tParam[1])); 
rc = pthread_create(&threads[2], NULL, Thread_Pool, (void *)&(tParam[2])); 
rc = pthread_create(&threads[3], NULL, Thread_Pool, (void *)&(tParam[3])); 

と:

このように、呼び出すことは完全に有効です。

+0

彼はポインタを逆参照していません。彼はポインタとして偽装された整数を渡し、そのポインタをintergerにキャストします。これは、POSIXスレッドでよく使われる概念です。自動整数変数をアドレスで渡すと、作成関数が終了して自動変数が破棄された後にスレッドが起動すると実行時エラーが発生する可能性があります(例:tParamスタックに割り当てられます)。 –

+0

@HristoIliev ah ok。まあ、彼は宣言はしていませんでした。私がやることではない(スレッドが作成される前に外側のスコープを破壊する)のではなく、整数型変数をポインタ型に渡すという考えが好きではありません。ポインタ型が4バイトであると仮定している人が最近私に多くの苦痛を与えたとしましょう。これが痛い例は、32ビットシステム上で 'uint64_t'を' void * 'を通して渡すことです。だから、それが本当に一般的な行為であれば、そうではありません。 –

関連する問題