4

pthread キャンセルのコード サンプルを次に示します。

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

void *my_routine(void *arg) {
  int i;
  for (i = 0; i < 10; i++) {
    printf("%d\n", i);
  }
  return NULL;
}

int main(void) {
  pthread_t thread;
  if (pthread_create(&thread, NULL, my_routine, NULL)) {
    fprintf(stderr, "Cannot create pthread\n");
    return 1;
  }
  usleep(20);
  pthread_cancel(thread);
  pthread_join(thread, NULL);
  //fflush(stdout);
  sleep(1);
  return 0;
}

私はコンパイルします:

gcc -pthread -Wall threadtest.c -o threadtest

実行すると、 の後に 追加の番号が出力されることがありsleep(1)ます。

この番号が重複している場合があります。

0
1
2
3
4
4  // printed after sleep(1)

時々そうではありません:

0
1
2
3
4
5  // printed after sleep(1)

I がのfflush(stdout)sleep(1)にある場合、追加の番号がすぐに出力されます。

printfスレッドをキャンセルするときのこの奇妙な動作を回避するにはどうすればよいですか?

ありがとうございました。

4

2 に答える 2

1

pthread_cancel を使用する場合は、スレッド ハンドラにもっと注意を払う必要があります。

pthread_cancel の man ページでは、これについて多くのことが説明されています。

男 pthread_cancel

マニュアルページで利用可能なサンプルプログラムを確認してください

スレッド ハンドラーの開始時に、pthread_setcancelstate システム コールを使用して PTHREAD_CANCEL_DISABLE を作成する必要があります。ハンドラーがキャンセル ポイント セット PTHREAD_CANCEL_ENABLE に達したとき。

メインでは、PTHREAD_CANCELED マクロを使用して、pthread_cancel が成功したかどうかを確認します。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void *my_routine(void *arg) {
  int i;
  //pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
  for (i = 0; i < 10; i++) {
    sleep(1);
    printf("%d\n", i);
  }
  //pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
  sleep(60);
  return NULL;
}
int main(void) 
{
  pthread_t thread;
  if (pthread_create(&thread, NULL, my_routine, NULL)) {
    fprintf(stderr, "Cannot create pthread\n");
    return 1;
  }
usleep(20);
pthread_cancel(thread);
pthread_join(thread, NULL);
//fflush(stdout);
sleep(1);
return 0;
}
  1. 最初に上記のプログラムをコンパイルして実行し、出力に注意してください。スレッドが作成された後、スレッド ハンドラが 1 秒待機してスリープし、その間に親スレッドがスレッドをキャンセルしてプロセスを終了するため、何も表示されずにプログラムが終了する場合があります。

  2. 次に、上記のプログラムから 2 つの pthread_setcancelstate() のコメントを外し、プログラムをコンパイルして実行します。1 から 9 まで表示されます。スレッドは PTHREAD_CANCEL_DISABLE に設定されているため、親 pthread_cancel はキャンセルせず、PTHREAD_CANCEL_ENABLE を待機します。スレッド ハンドラーが PTHREAD_CANCEL_ENABLE を満たすと、親スレッドはスレッドをキャンセルします。

  3. 出力に注意するとき。その前に親がスレッドをキャンセルするため、ハンドラは sleep(60) にとどまりません。

于 2013-06-20T09:43:43.457 に答える