2

スレッド 1、スレッド 2、スレッド 3、およびスレッド 4 を作成するための 4 つのスレッドがあります。

pthread_create(thread1,NULL,thread_func1,NULL);
pthread_create(thread2,NULL,thread_func2,NULL);
pthread_create(thread3,NULL,thread_func3,NULL);
pthread_create(thread4,NULL,thread_func4,NULL);

デバッグを見ると、起動されたスレッドの順序がソース コードで定義されているものと同じではありません。定義できる順序でスレッドを起動するソリューションはありますか?

4

4 に答える 4

4

起動順序シーケンシャルであり、作成呼び出しは書き込まれた順序で行われます。

ただし、スケジューラーは、何らかの理由で、新しく起動されたスレッドを希望の順序でスケジュールしていません。順序が重要な場合、おそらくスレッドはあなたが望むものではありませんか?スレッドの大きな利点は、スレッドが常に順番にスケジュールされるとは限らないことです。

本当に必要な場合は、同期プリミティブ(一連のミューテックス、またはcondvarなど)を使用して、特定のポイントまでが予測可能な順序で発生するようにすることができますが、それ以降は、順序はまだ気まぐれになりますスケジューラー。例として、このコードは、各スレッドが作成された順序でIDを出力することを保証します。

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

static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void sync_threads(const int num, int *cur) {
  pthread_mutex_lock(&mut);
  while (*cur != num) {
    pthread_cond_wait(&cond, &mut);
  }
  // Do work that must happen in order here:
  printf("Thread: %d\n", num);
  ++*cur;
  pthread_mutex_unlock(&mut);
  pthread_cond_broadcast(&cond);
}

static int num = 1;

void *thread1(void *d) {
  sync_threads(1,&num);
  while (1); // Rest of work happens whenever
  return NULL;
}

void *thread2(void *d) {
  sync_threads(2,&num);
  while (1);
  return NULL;
}

void *thread3(void *d) {
  sync_threads(3,&num);
  while (1);
  return NULL;
}

void *thread4(void *d) {
  sync_threads(4,&num);
  while (1);
  return NULL;
}

int main() {
  pthread_t t1,t2,t3,t4;
  pthread_create(&t1, NULL, thread1, NULL);
  pthread_create(&t2, NULL, thread2, NULL);
  pthread_create(&t3, NULL, thread3, NULL);
  pthread_create(&t4, NULL, thread4, NULL);
  while(1) {
    // some work
  }
}

私はwhile(1);実際に起こっている作業をシミュレートするために使用しました。これは、「現在の」スレッドを保護するミューテックス、つまり初期化の順序と、スリープ/ウェイクアップを可能にするcondvarを使用して行われます。すべてのスレッドにブロードキャストし、スレッドは次にどのスレッドが稼働しているかを確認します。ブロードキャストをスキップするシステムとして設計することもできますが、それは比較的わずかな利益で物事を複雑にします。

他のポイントで必要に応じて同期を追加することもできますが、同期を多くするほど、そもそもスレッドを持つことのポイントが少なくなります。

理想的には、予測可能な順序で物事を行う必要がある場合は、スレッドがスポーンする直後ではなく、スレッドをスポーンする前に実行する必要があります。例:

fixed_init_for_thread1();
fixed_init_for_thread2();
fixed_init_for_thread3();
fixed_init_for_thread4();

pthread_create(thread1,NULL,thread_func1,NULL);
pthread_create(thread2,NULL,thread_func2,NULL);
pthread_create(thread3,NULL,thread_func3,NULL);
pthread_create(thread4,NULL,thread_func4,NULL);

そのため、スレッドが作成されるまでに、どちらが実際に最初に実行される機会が与えられるかは気になりません。

于 2012-05-16T10:43:06.500 に答える
1

ここで私が使用したソリューションの後

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

static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static bool wait = TRUE;

void thread_sync() {
  pthread_mutex_lock(&mut);
  wait = FALSE;
  pthread_cond_signal(&cond);
  pthread_mutex_unlock(&mut);
}
void thread_wait_sync() {
  pthread_mutex_lock(&mut);
  if (wait==TRUE)
  {
      pthread_cond_wait(&cond,&mut);
  }
  wait = TRUE;
  pthread_mutex_unlock(&mut);
}

void *thread1(void *d) {
  thread_sync();
  while (1); // Rest of work happens whenever
  return NULL;
}

void *thread2(void *d) {
  thread_sync();
  while (1);
  return NULL;
}

void *thread3(void *d) {
  thread_sync();
  while (1);
  return NULL;
}

void *thread4(void *d) {
  while (1);
  return NULL;
}

int main() {
  pthread_t t1,t2,t3,t4;
  pthread_create(&t1, NULL, thread1, NULL);
  thread_wait_sync();
  pthread_create(&t2, NULL, thread2, NULL);
  thread_wait_sync();
  pthread_create(&t3, NULL, thread3, NULL);
  thread_wait_sync();
  pthread_create(&t4, NULL, thread4, NULL);
  while(1) {
    // some work
  }
}
于 2012-05-30T17:22:17.163 に答える
1

どのスレッドが最初に実行されたかは気にしないと思います。4 つのスレッドの一意の識別子だけが必要な場合は、pthread_self を確認してください。ID を連続させるには、スレッド内から ID アロケーターを呼び出します。または ID を生成し、pthread_create を呼び出すときにユーザー パラメータとして渡します。

于 2012-05-16T12:27:49.087 に答える
0
Move 'pthread_create(thread2,NULL,thread_func2,NULL);' into thread_func1()
Move 'pthread_create(thread3,NULL,thread_func2,NULL);' into thread_func2()
Move 'pthread_create(thread4,NULL,thread_func2,NULL);' into thread_func3()

これは最近投稿された他の質問に非常に近く、エラーと同じです。

于 2012-05-16T20:59:29.883 に答える