pthread_cond_timedwait 修改系统时间竟会导致其提前结束

pthread 条件变量使用注意

  • 使用 pthread_cond_timedwait 等待条件变量时,其默认使用的为系统时间,若在其等待期间修改系统时间,则会导致其提前结束。

测试步骤

  • 运行以下代码。

  • 使用 date 命令查看系统时间,假设输出为 Thu Jan 1 08:01:53 AM CST 1970

  • 使用 date -s 08:03:53 设置系统时间,程序会立刻退出,并打印 wait timed out

    c 复制代码
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <errno.h>
    #include <unistd.h>
    
    pthread_cond_t g_cond;
    pthread_mutex_t g_mutex;
    
    void* thread1_func(void* arg)
    {
        // 必须先获取互斥锁
        pthread_mutex_lock(&g_mutex);
    
        // 获取当前时间
        struct timespec ts;
        clock_gettime(CLOCK_REALTIME, &ts);
        // 设置等待时间为 100 秒
        ts.tv_sec += 100;
    
        // 等待条件变量被唤醒,或者等待时间超时
        printf("waiting cond signal\n");
        int ret = pthread_cond_timedwait(&g_cond, &g_mutex, &ts);
        if (ret == 0) {
            printf("get cond signaled\n");
        } else if (ret == ETIMEDOUT) {
            printf("wait timed out\n");
        } else {
            printf("wait failed\n");
        }
    
        // 解锁
        pthread_mutex_unlock(&g_mutex);
        return NULL;
    }
    
    int main()
    {
        pthread_cond_init(&g_cond, NULL);
        pthread_mutex_init(&g_mutex, NULL);
    
        // 创建线程
        pthread_t th1;
        pthread_create(&th1, NULL, thread1_func, NULL);
    
        // 等待线程结束
        pthread_join(th1, NULL);
    
        pthread_mutex_destroy(&g_mutex);
        pthread_cond_destroy(&g_cond);
        return 0;
    }

解决方案

  • 初始化条件变量时,设置其使用稳定时钟即可。

  • 示例代码如下:

    c 复制代码
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <errno.h>
    #include <unistd.h>
    
    pthread_cond_t g_cond;
    pthread_mutex_t g_mutex;
    
    void* thread1_func(void* arg)
    {
        // 必须先获取互斥锁
        pthread_mutex_lock(&g_mutex);
    
        // 获取当前时间
        struct timespec ts;
        // 此处与上文不同
        clock_gettime(CLOCK_MONOTONIC, &ts);
        // 设置等待时间为 100 秒
        ts.tv_sec += 100;
    
        // 等待条件变量被唤醒,或者等待时间超时
        printf("waiting cond signal\n");
        int ret = pthread_cond_timedwait(&g_cond, &g_mutex, &ts);
        if (ret == 0) {
            printf("get cond signaled\n");
        } else if (ret == ETIMEDOUT) {
            printf("wait timed out\n");
        } else {
            printf("wait failed\n");
        }
    
        // 解锁
        pthread_mutex_unlock(&g_mutex);
        return NULL;
    }
    
    int main()
    {
        pthread_condattr_t condattr;
        pthread_condattr_init(&condattr);
        // 设置使用稳定时钟
        pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC);
        pthread_cond_init(&g_cond, &condattr);
        pthread_mutex_init(&g_mutex, NULL);
    
        // 创建线程
        pthread_t th1;
        pthread_create(&th1, NULL, thread1_func, NULL);
    
        // 等待线程结束
        pthread_join(th1, NULL);
    
        pthread_mutex_destroy(&g_mutex);
        pthread_cond_destroy(&g_cond);
        return 0;
    }
相关推荐
莫回首�几秒前
ubuntu 20.04 多网卡配置,遇到问题总结
linux·网络·ubuntu
网络安全许木9 分钟前
自学渗透测试第11天(Linux压缩解压与磁盘管理)
linux·网络安全·渗透测试
沫璃染墨2 小时前
C++ string 从入门到精通:构造、迭代器、容量接口全解析
c语言·开发语言·c++
lifewange3 小时前
Linux ps 进程查看命令详解
linux·运维·服务器
功德+n3 小时前
Linux下安装与配置Docker完整详细步骤
linux·运维·服务器·开发语言·docker·centos
计算机安禾4 小时前
【数据结构与算法】第36篇:排序大总结:稳定性、时间复杂度与适用场景
c语言·数据结构·c++·算法·链表·线性回归·visual studio
左手厨刀右手茼蒿4 小时前
Linux 内核中的块设备驱动:从原理到实践
linux·嵌入式·系统内核
杨云龙UP4 小时前
从0到1快速学会Linux操作系统(基础),这一篇就够了!
linux·运维·服务器·学习·ubuntu·centos·ssh
HXQ_晴天4 小时前
Ubuntu 设置中文输入法
linux·运维·ubuntu