2

私は C++ と pthreads を使用しており、pthread が作成された順序を調べる必要があります。どの pthread が最初に作成されたか、2 番目に作成されたかなどを示す一意の整数が必要です。

私の最初のアイデアは を使用することでしたがpthread_self()、この関数はかなり巨大な乱数のような一意の ID を返します。

2 番目のアイデアは、ループ内の create メソッドで使用していたカウンターを渡すことでした。

pthread_t pthreads[pthreadsNum]; 
    for(int i = 0; i < pthreadsNum; i++){
        if (pthread_create(&pthreads[i], NULL, process, (void *)&i) != 0){
            cerr << "Error in pthread creation" << endl;
            return PTHREAD_CREATION_FAILED;
        }
    }

ただし、これも機能しません。私の関数processでは、カウンターの値を出力しようとしましたiが、混乱が生じます。一部の pthread がそれとカオス ルールを受信して​​いる間に、どうやらカウンターが更新されるようです。

void *process(void* arg_ptr)
{
  int i = *((int*)arg_ptr);
  cout << i << endl;
  //rest of code
}

私にランダムな出力を与える: 3 3 4 3 そして、この同じランダムな出力の他の組み合わせ。

結論として、私は次の質問があります。

1 - 私は何を間違っていますか?

2 - 安全かつ効率的にカウンターを通過するにはどうすればよいですか?

3 - pthreads が作成された順序を取得する別の解決策はありますか?

助けてくれてありがとう:S

4

3 に答える 3

2

のアドレスを渡しましたi。スレッドが の値を読み取ると、i変更されている可能性があります。作成したスレッドと、ループをi実行して値を更新するメインスレッドが並行して実行されるためです。

もし私がこれをしていたら、私は次のようにします:

pthread_t pthreads[pthreadsNum];
int ids[pthreadsNum];
for(int i = 0; i < pthreadsNum; i++){
    ids[i] = i;
    if (pthread_create(&pthreads[i], NULL, process, (void *)&ids[i]) != 0){
于 2013-03-11T19:50:37.280 に答える
2

一部の pthread がそれを受信して​​いる間にカウンターが更新され、カオス ルール

はい、同期せずに並列処理を使用すると、最終的にはこのようになります。期待どおりの順序で処理が行われることはありません。

まさにあなたの状況で、カウンターをスレッドに渡す簡単な方法は、ポインターにキャストすることです。使用する整数型がポインターと同じサイズであることを確認するには、以下を使用しますuintptr_t(標準では、ポインターと (u)intptr_t の間の変換が損失なしで保証されます)。

#include <stdint.h>

for (uintptr_t i = 0; i < pthreadsNum; ++i) {
    if (pthread_create(&pthreads[i], NULL, process, reinterpret_cast<void*>(i)) != 0) {
        ...

void* process(void* arg_ptr) {
    uintptr_t i = reinterpret_cast<uintptr_t>(arg_ptr);
    ...

しかし、cHao のコメントは非常に的を射ています。スレッドの実行順序をこれほど細かく制御する必要がある場合は、問題が発生します。同期 (ミューテックス、条件変数など) を使用して、スレッド間通信に使用される重要なデータ構造 (メッセージ キュー、その他の複雑なオブジェクト、または単純なスカラーなど) を保護することをお勧めします。この細かい制御は必要ありません。

于 2013-03-11T19:48:09.737 に答える
0

まず、2 つの質問があります。なぜこの情報が必要なのですか? どのような問題を解決しようとしていますか?

そうは言っても、pthread_create何らかのデータ構造 (たとえば、std::vector<> またはリンクされたリスト) を維持する関数を単純にラップしないのはなぜですか。ラッパーは pthread_create を呼び出し、作成された各スレッドのスレッド ID をデータ構造に追加しますか? ロック/シリアル化を追加することを忘れないでください。また、必要に応じて、終了したスレッドを削除するコード。

最後に、作成の「順序」が必要な場合は、データ構造でスレッド ID の「インデックス」を見つけるだけです。

于 2013-03-11T22:13:46.210 に答える