You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

printf()作为安全取消点的机制及线程取消相关问题咨询

线程取消与printf、time命令的疑问

测试代码

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

void *thread_function(void *arg)
{
    while(1)
    {
        printf("hello\n"); 
        //sleep(1);
    }
    return NULL;
}

int main()
{
    pthread_t thread;

    if(pthread_create(&thread, NULL, thread_function, NULL) != 0)
    {
        perror("Failed to create a thread");
        return -1;
    }

    printf("After sleep in main thread\n");
    if (pthread_cancel(thread) != 0) {
        perror("Failed to cancel thread");
        return EXIT_FAILURE;
    }

    pthread_join(thread, NULL);
    printf("Thread is cancelled\n");
}

疑问点

  • 当线程函数中用sleep()时,线程能立即被取消;但用printf()时,取消线程需要耗时。已知sleep()是安全取消点,printf()可能是安全取消点,想知道printf()在运行的哪个阶段会成为取消点并触发线程取消?
  • 用time命令运行程序时,显示的运行时长为2秒,但实际感觉运行时间更长,这是为什么?

问题解答

1. printf()何时成为取消点触发线程取消

printf()本身不是POSIX标准强制规定的取消点,但它内部调用的底层I/O函数(比如write())是标准定义的安全取消点。只有当printf()触发缓冲区刷新、调用到底层系统调用时,才会触发取消检查:

  • 比如默认行缓冲模式下,输出换行符\n会触发缓冲刷新;或者缓冲区被填满达到阈值时,printf()会调用write()向内核写入数据。此时write()作为取消点,会检查线程是否存在未处理的取消请求,一旦检测到就会终止线程。
  • 如果缓冲区没满,printf()只是把数据写入用户态缓冲区,不会进入系统调用,也就不会触发取消检查。线程会继续循环执行printf,直到某次操作触发缓冲刷新、调用到底层系统调用时,才会响应取消请求——这就是用printf时取消线程需要耗时的原因。

2. time命令显示时长与实际感觉不符的原因

time命令统计的是进程的CPU时间(包括用户态CPU时间和内核态CPU时间),而不是你主观感受到的墙上时钟时间(实际流逝的时间):

  • 当线程疯狂调用printf时,大部分时间要么在用户态填充缓冲区,要么等待内核处理I/O(此时进程会进入睡眠状态,不占用CPU)。time只统计进程实际占用CPU的时间,而你感受到的是从程序启动到结束的完整时间,其中包含了进程等待I/O、被调度器切换出去的时间。
  • 另外,大量的printf输出会让终端I/O成为瓶颈,进程会频繁陷入睡眠等待终端接收数据,这部分等待时间不会被计入time的CPU时间统计,但会让你觉得程序运行了更久。

内容的提问来源于stack exchange,提问作者Мария Шипаева

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 08:22:23