0

これが私がやろうとしていることです:

  1. メインスレッドから 10 個の posix スレッドを開始します。
  2. 10 個のスレッドのそれぞれが何らかの操作を 100 回実行します。

これは私が助けを必要としているものです。

  1. thread_1 がたとえば 10 秒間その処理を実行できるようにしたい (スレッド 2 ~ 10 が中断されている間)。次に、スレッド 1 とスレッド 3 ~ 10 が中断されている間、スレッド 2 がその処理を実行できるようにします。

どうすればいいですか?いくつかの pthread チュートリアルを見ていましたが、やろうとしていることは非常に簡単ですが、物事は複雑に見えました。

4

3 に答える 3

3

OPの質問が理にかなっているのかどうかについての議論に加えて、考えられる解決策は次のとおりです。

スケジュールするスレッドごとにシグナル ハンドラーをインストールします。このハンドラーは say でトリガーされSIGUSR1、内部的には への呼び出しを呼び出すだけpause()です。

pause()スレッド関数はすべて、作成直後にすべてのスレッドを一時停止する への呼び出しで始まります。

を使用して、スケジュールするすべてのスレッドを作成しますpthread_create()。作成された pthread を配列に格納しpthreadsます。

(からpthread)実行する最初の pthread を に割り当てpthread_firstます。

スケジューリング呼び出しを開始するpthread_kill(pthread_first, SIGUSR2)には、最初に実行されるスレッドを再開します (pause()そのブロックをオンにして戻ります)。にpthread_currentなるpthread_first

実際にスケジューリングを実行するには、追加のスレッド (おそらくメイン スレッド) が無限にループし、現在のスレッドを中断するためにsleep(SCHEDULING_INTERVALL)呼び出しpthread_kill(pthread_current, SIGUSR1)ます (そのシグナル ハンドラーを呼び出し、これを に実行することによりpause())。次にpthread_kill(pthread_next, SIGUSR2)、次のスレッドを再開するために呼び出します (pause()ブロックをオンにして戻ります)。スレッドの作成中に埋められた配列から、 becomeとpthreat_currentbecome別のエントリを作成します。pthread_nextpthread_nextpthread

ただし、次のことに注意してください。

シグナルによって中断されて中断されたスレッドpause()は、共有リソースで何らかの作業を行っている最中に捕捉され、再開されるまでそのままである可​​能性があるため、互いに足を踏み入れる可能性は非常に高くなります。

他のすべての人へ:はい、私を倒してください;-)


アップデート:

同等の例:

#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>

#define THREADSMAX (3)
#define SCHEDULING_INTERVALL (5) /* seconds */

void
sigusr_handler(int signo)
{
  if (SIGUSR1 == signo)
    {
      pause();
    }
}

void *
thread_function(void * pv)
{
  intptr_t iThread = (intptr_t) pv;

  pause();

    {
      int i = 0;
      for (;;)
        {
          printf("%d: %d\n", (int) iThread, i++);
          sleep(1);
        }
    }

  pthread_exit(NULL);
}

int
main(int argc, char ** argv)
{
  struct sigaction signal_action;
  memset(&signal_action, 0, sizeof(signal_action));
  signal_action.sa_handler = sigusr_handler;
  sigemptyset(&signal_action.sa_mask);

  sigaction(SIGUSR1, &signal_action, NULL);
  sigaction(SIGUSR2, &signal_action, NULL);

    {
      pthread_t threads[THREADSMAX] =
        { 0 };

      intptr_t iThread = 0;

      /* create threads */
      for (; iThread < THREADSMAX; ++iThread)
        {
          int iResult = pthread_create(&threads[iThread], NULL, thread_function,
              (void *) iThread);
          if (iResult)
            {
              errno = iResult;
              perror("pthread_created()");
              exit(1);
            }
        }

      sleep(1); /* Unreliable workaround: Try to make sure all threads have started and block in "pause()". See comments on how this might be fixed nicely ... */

      /* scheduling loop */
      for (iThread = 0;; ++iThread)
        {
          if (THREADSMAX == iThread)
            {
              iThread = 0;
            }
            /* Resume current thread */
            {
              int iResult = pthread_kill(threads[iThread], SIGUSR2);
              if (iResult)
                {
                  errno = iResult;
                  perror("pthread_kill(..., SIGUSR2)");
                  exit(2);
                }
            }

          sleep(SCHEDULING_INTERVALL);

          /* Suspend current thread */
            {
              int iResult = pthread_kill(threads[iThread], SIGUSR1);
              if (iResult)
                {
                  errno = iResult;
                  perror("pthread_kill(..., SIGUSR1)");
                  exit(3);
                }
            }
        }
    }

  return 0;
}

期待される出力:

0: 0
0: 1
0: 2
0: 3
0: 4
1: 0
1: 1
1: 2
1: 3
1: 4
2: 0
2: 1
2: 2
2: 3
2: 4
0: 5
0: 6
0: 7
0: 8
0: 9
1: 5
1: 6
1: 7
1: 8
1: 9
2: 5
2: 6
...
于 2013-05-04T11:08:15.063 に答える
1
  1. POSIX スレッド: 条件変数 - ポイントは何ですか?
  2. スレッドの結合と切り離し: ここに画像の説明を入力
  3. とスケジューラを使用するsleep()と、コンテキストが別のプロセスに切り替わります。IMO それはそれほど悪い解決策ではありません。シナリオによっては 100 ミリ秒が多くの時間であり、別のシナリオでは非常に短いため、一般的ではありません。
  4. 条件変数またはある種のシンクロナイザーを自分で実装しますが、実際にはお勧めしません。
于 2013-05-03T23:40:41.217 に答える
1

あなたはあなたの要求をうまく述べていません。スレッドはすべて独立したデータで動作しますか (スレッド間で同期する必要はありません)? もしそうなら、10 秒単位で独自のコース スケジュールを作成しようとすること自体がナンセンスです。彼ら全員を走らせて、自分のことをさせてください。もちろん、タイマーシグナルを使用し、どのスレッドがシグナルをブロックするかを制御することで、要求したことを達成するのはかなり簡単ですが、まったく役に立ちません。

一方、スレッド間にデータの依存関係がある場合、「10 秒間実行してから別のスレッドに制御を移す」というパターンは無効です。最初のスレッドが保持しているロックのために次のスレッドが続行できない場合、デッドロックが発生する可能性があります。(制御は最終的に最初のスレッドに戻るため、完全にデッドロックではないと思いますが、複数のロックが関係している場合、遅延が非常に大きくなる可能性があります。)代わりに、この場合、どのスレッドは、データの流れによって制御されて実行されます。

于 2013-05-04T02:39:54.600 に答える