gpt4 book ai didi

c - pthread_cond_timedwait() 如何工作?

转载 作者:行者123 更新时间:2023-12-03 12:58:50 26 4
gpt4 key购买 nike

所以我试图了解 pthread_cond_timedwait() 是如何工作的,因为我在我的项目上进行同步时遇到了一些问题。这是我想出的代码,但它并没有像我想象的那样工作。我的目标是打印时间,等待 2 秒,然后再次打印时间以查看时间的流逝。

//gcc -Wall -pthread timedwait.c -o  exe


#define _OPEN_THREADS
#include <pthread.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <stdlib.h>




int main() {
pthread_cond_t cond;
pthread_mutex_t mutex;
time_t T;
struct timespec t;

if (pthread_cond_init(&cond, NULL) != 0) {
perror("pthread_cond_init() error");
exit(2);
}


time(&T);
t.tv_sec = T + 2;
printf("starting timedwait at %s", ctime(&T));
pthread_cond_timedwait(&cond, &mutex, &t);
time(&T);
printf("timedwait over at %s", ctime(&T));
}

最佳答案

您的代码有几个问题,最重要的问题都与使用值不确定的变量有关。

您的另一个答案讨论了您未能初始化结构的某些成员的事实 t ,这确实是一个重大缺陷。当我修改你的程序以捕获 pthread_cond_timedwait 的返回值时调用,我发现它返回 EINVAL ,表示无效的参数。有两个很好的替代方案可以解决这个问题:

  • 使用初始化程序声明该变量:
    struct timespec t = { 0 };
    // ...
    t.tv_sec = T + 2;

    该特定初始化程序将第一个成员显式设置为零,所有其他成员都隐式设置为默认(零)值——初始化的特征不适用于逐个成员分配。这不仅比显式分配每个成员更方便,而且还处理该结构类型的特定实现版本可能具有的任何未记录成员。
  • 或通过服务于该目的的函数为(整个)结构设置一个值。例如,
    struct timespec t;
    clock_gettime(CLOCK_REALTIME, &t);
    // ... no need for T or time() ...
    t.tv_sec += 2;

    这需要一个不依赖于结构原始值的函数(例如 clock_gettime )。

  • 更正变量 t的初始化问题后,结果程序对我来说仍然失败,但出现不同的错误: EPERM , 表示该操作不允许用于特定的参数组合。对于这个特定的函数,那是因为在调用时互斥锁没有被调用线程锁定,但实际上比这更糟糕:互斥锁甚至没有初始化。可以通过 pthread_mutex_init 初始化它,但如果您不关心设置任何非默认属性,那么静态初始化程序更方便:
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    int result;
    // ...
    result = pthread_mutex_lock(&mutex);

    (注意:条件变量也有一个静态初始值设定项。)

    此外,正如我在评论中所观察到的,您不会始终检查函数调用的返回值。如果您不关心调用的成功或效果,或者至少可以合理地忽略可能发生的任何失败,但您依赖特定结果来执行程序的后续行为,则可以省略此类检查正确地说,检查返回值是安全编程的一个基本问题。

    最后,作为一个小问题,GCC 和 GLibc 对 _OPEN_THREADS 没有任何意义。功能测试宏,它不是由 POSIX 定义的。它似乎特定于 IBM 的工具链。在您的情况下它可能无害,但它绝对不合适且无益,即使在它适用的环境中,似乎也有更好的方法来获得它提供的相同效果。

    您程序的这种变体解决了所有这些问题:
    // gcc -Wall -pthread timedwait.c -o  exe

    #include <pthread.h>
    #include <stdio.h>
    #include <time.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <string.h>

    int main() {
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    struct timespec t;
    int result;

    result = pthread_mutex_lock(&mutex);
    if (result != 0) {
    fprintf(stderr, "pthread_mutex_lock: %s\n", strerror(result));
    exit(EXIT_FAILURE);
    }

    result = clock_gettime(CLOCK_REALTIME, &t);
    if (result == -1) {
    perror("clock_gettime");
    exit(EXIT_FAILURE);
    }

    // Return-value check is non-essential here:
    printf("starting timedwait at %s", ctime(&t.tv_sec));

    t.tv_sec += 2;
    result = pthread_cond_timedwait(&cond, &mutex, &t);
    if (result != ETIMEDOUT) {
    fprintf(stderr, "%s\n", strerror(result));
    }

    result = clock_gettime(CLOCK_REALTIME, &t);
    if (result == -1) {
    perror("clock_gettime");
    exit(EXIT_FAILURE);
    }

    // Return-value check is non-essential here:
    printf("timedwait over at %s", ctime(&t.tv_sec));

    // Return-value check is non-essential here, because we'll just exit anyway:
    pthread_mutex_unlock(&mutex);
    }

    最后,我观察到在我自己的编程中我通常定义一个或多个宏来支持返回值检查。我发现使用这样的宏而不是为每个检查显式编写代码使程序的整体流程更加清晰,更不用说节省了我的击键次数。我没有在上面证明这一点,尽管即使在如此短的程序中,这种方法的用处也可能已经很明显了。

    关于c - pthread_cond_timedwait() 如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59112776/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com