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)before sleep(1),则立即打印附加号码。

printf取消线程时如何避免这种奇怪的行为?

谢谢你。

4

2 回答 2

1

您可以在执行时禁用取消printf()并添加显式取消点:

int cancel_state = 0;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state);
printf("%d\n", i);
pthread_setcancelstate(cancel_state);
pthread_testcancel();

(为了便于阅读,省略了错误检查)

于 2013-06-20T08:31:17.503 回答
1

使用 pthread_cancel 时,您应该更加注意线程处理程序。

pthread_cancel 的手册页对此进行了很多解释。

人 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. 然后取消上面程序中两个 pthread_setcancelstate() 的注释,现在编译运行程序。它现在将显示从 1 到 9。因为线程设置为 PTHREAD_CANCEL_DISABLE,所以父 pthread_cancel 不会取消并等待 PTHREAD_CANCEL_ENABLE。当线程处理程序遇到 PTHREAD_CANCEL_ENABLE 时,父线程将取消线程。

  3. 当你注意到输出时。处理程序不会保持睡眠(60),因为在此之前父级将取消线程。

于 2013-06-20T09:43:43.457 回答