36

メインスレッドがすべての(p)スレッドが完了するのを待ってから終了するようにしたいだけです。

スレッドはさまざまな理由で何度も行き来しますが、私は本当にすべてのスレッドを追跡したくありません。スレッドがすべてなくなったときを知りたいだけです。

wait()は子プロセスに対してこれを行い、子が残っていない場合はECHILDを返しますが、waitは(p)スレッドを処理しません(動作しているように見えます)。

私は本当に、すべての未処理のスレッドのリストを(それらが行き来するときに)保持し、それぞれでpthread_joinを呼び出さなければならないという問題を経験したくありません。

これを行うための迅速で汚い方法はありますか?

4

5 に答える 5

27

すべてのスレッドが完了した後で、メイン スレッドに特定の処理をさせたいですか?

そうでない場合は、メイン スレッドpthread_exit()を返す (または呼び出すexit()) 代わりに、単純に呼び出すことができます。

返された場合main()は、暗黙的に を呼び出します (または、呼び出したかのように動作します) exit()。これにより、プロセスが終了します。ただし、返される代わりにmain()呼び出しが行われた場合pthread_exit()、その暗黙的な呼び出しexit()は発生せず、プロセスはすぐには終了しません。すべてのスレッドが終了したときに終了します。

あまりにも多くのクイックアンドダーティを取得することはできません.

違いを確認できる小さなサンプル プログラムを次に示します。-DUSE_PTHREAD_EXITコンパイラに渡して、すべてのスレッドが終了するまでプロセスが待機することを確認します。そのマクロを定義せずにコンパイルして、プロセスがトラック内のスレッドを停止することを確認します。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>

static
void sleep(int ms)
{
    struct timespec waittime;

    waittime.tv_sec = (ms / 1000);
    ms = ms % 1000;
    waittime.tv_nsec = ms * 1000 * 1000;

    nanosleep( &waittime, NULL);
}

void* threadfunc( void* c)
{
    int id = (int) c;
    int i = 0;

    for (i = 0 ; i < 12; ++i) {
        printf( "thread %d, iteration %d\n", id, i);
        sleep(10);
    }

    return 0;
}


int main()
{
    int i = 4;

    for (; i; --i) {
        pthread_t* tcb = malloc( sizeof(*tcb));

        pthread_create( tcb, NULL, threadfunc, (void*) i);
    }

    sleep(40);

#ifdef USE_PTHREAD_EXIT
    pthread_exit(0);
#endif

    return 0;
}
于 2011-05-27T18:07:52.783 に答える
23

適切な方法は、すべての pthread_id を追跡することですが、迅速かつ汚い方法を求めたので、ここにあります。基本的:

  • 実行中のスレッドの総数を保持するだけで、
  • pthread_create を呼び出す前に、メイン ループでそれをインクリメントします。
  • 各スレッドが終了するたびにスレッド数を減らします。
  • 次に、カウントが 0 に戻るまで、メイン プロセスの最後でスリープします。

.

volatile int running_threads = 0;
pthread_mutex_t running_mutex = PTHREAD_MUTEX_INITIALIZER;

void * threadStart()
{
   // do the thread work
   pthread_mutex_lock(&running_mutex);
   running_threads--;
   pthread_mutex_unlock(&running_mutex);
}

int main()
{
  for (i = 0; i < num_threads;i++)
  {
     pthread_mutex_lock(&running_mutex);
     running_threads++;
     pthread_mutex_unlock(&running_mutex);
     // launch thread

  }

  while (running_threads > 0)
  {
     sleep(1);
  }
}
于 2011-05-27T17:04:36.763 に答える
2

スレッドを追跡したくない場合は、スレッドを切り離して気にする必要はありませんが、スレッドがいつ終了したかを知るには、もう少し先に進む必要があります。

1つのトリックは、スレッドのステータスのリスト(リンクリスト、配列など)を保持することです。スレッドが開始すると、配列内のステータスがTHREAD_STATUS_RUNNINGのように設定され、終了する直前にステータスがTHREAD_STATUS_STOPPEDのように更新されます。次に、すべてのスレッドが停止したかどうかを確認する場合は、この配列を繰り返し処理して、すべてのステータスを確認できます。

ただし、このようなことを行う場合は、一度に1つのスレッドのみが配列にアクセス(読み取りおよび書き込み)できるように配列へのアクセスを制御する必要があるため、配列にミューテックスを使用する必要があることを忘れないでください。

于 2011-05-27T15:50:02.037 に答える
1

すべてのスレッド ID のリストを保持し、それぞれに対して pthread_join を実行できます。もちろん、スレッド ID リストへのアクセスを制御するにはミューテックスが必要です。また、反復中に変更できるある種のリスト、おそらく std::set<pthread_t> が必要になりますか?

int main() {
   pthread_mutex_lock(&mutex);

   void *data;
   for(threadId in threadIdList) {
      pthread_mutex_unlock(&mutex);
      pthread_join(threadId, &data);
      pthread_mutex_lock(&mutex);
   }

   printf("All threads completed.\n");
}

// called by any thread to create another
void CreateThread()
{
   pthread_t id;

   pthread_mutex_lock(&mutex);
   pthread_create(&id, NULL, ThreadInit, &id); // pass the id so the thread can use it with to remove itself
   threadIdList.add(id);
   pthread_mutex_unlock(&mutex);  
}

// called by each thread before it dies
void RemoveThread(pthread_t& id)
{
   pthread_mutex_lock(&mutex);
   threadIdList.remove(id);
   pthread_mutex_unlock(&mutex);
}
于 2014-02-23T21:32:57.790 に答える