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;
    }
相关推荐
哎呦喂我去去去21 分钟前
C#实现屏幕墙:同时监控多个电脑桌面(支持Windows、信创Linux、银河麒麟、统信UOS)
linux·windows·c#
easy_coder2 小时前
Linux LVM 知识文档
linux·运维
caishenzhibiao2 小时前
期货先行者主图 同花顺期货通指标
java·c语言·c#
小小的木头人2 小时前
Ubuntu 使用 udev + systemd + UUID 实现 USB 硬盘自动挂载
linux·运维·ubuntu
kaoa0004 小时前
Linux入门攻坚——84、网络虚拟化技术-1
linux·运维·服务器
RisunJan4 小时前
Linux命令-shutdown(安全关闭或重启系统)
linux·服务器·安全
2601_965798475 小时前
MTDb Movie & TV Database Script Setup, Caching, and SEO Guide
linux·服务器·数据库·php
NoteStream5 小时前
【c语言基础】C语言常见概念
c语言·开发语言·编辑器
我头发多我先学5 小时前
linux系统编程:初识进程
linux·运维·服务器
caishenzhibiao5 小时前
先行者副图 同花顺期货通指标
java·c语言·c#