取消pthread和printf行为

时间:2013-06-20 08:23:07

标签: c pthreads printf cancellation

以下是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)

如果我fflush(stdout)之前sleep(1),则会立即打印其他号码。

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

谢谢。

2 个答案:

答案 0 :(得分:0)

您可以在执行printf()时停用取消并添加明确的取消点:

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

(为了便于阅读,遗漏了错误检查)

答案 1 :(得分:0)

使用pthread_cancel时,你应该更加小心线程处理程序。

pthread_cancel的手册解释了很多。

  

man pthread_cancel

检查手册页中提供的示例程序

当线程处理程序启动时,您必须在pthread_setcancelstate系统调用的帮助下进行PTHREAD_CANCEL_DISABLE,当处理程序满足取消点设置PTHREAD_CANCEL_ENABLE时。

在主要检查pthread_cancel成功与否是在PTHREAD_CANCELED宏的帮助下。

#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),因为在该父程序将取消该程序之前。