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;
    }
相关推荐
木子欢儿2 小时前
openconnect Linux客户端安装 以及开机自启和登录
linux·运维·服务器
..Dauntless..3 小时前
【Linux】文件系统(一)
linux·运维·服务器
·present·3 小时前
CSAPP(lecture 4_01)
c语言·c++
GeW5 小时前
新质生产力路线图:从Linux到数据库,企业落地要点都在这
linux
IMPYLH5 小时前
Linux 系统备份与镜像
linux·服务器·网络
qetfw5 小时前
Bash 字符串处理:参数展开、序列与脚本执行方式
linux·开发语言·chrome·bash
hhwyqwqhhwy5 小时前
设备树之 provider 和 consumer
java·linux·前端
aaa最北边6 小时前
Linux 上的交叉编译
linux·运维·服务器
小张成长计划..7 小时前
【Linux】27:日志
linux·运维·服务器
本地化文档7 小时前
llvm-libc-docs-l10n
c语言·github·gitcode·sphinx·llvm·crowdin