因此,我试图了解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));
}
如果您看到的是等待或多或少立即完成,而不是按照请求等待2秒钟,那么几乎可以肯定是因为timespec
对象包含垃圾。
tv_sec
当然包含秒数,但是tv_nsec
包含纳秒,可能很容易通过说:我不关心它是大于还是小于2秒几纳秒来消除这一点。
但是那不是它的工作方式。如果堆栈上的垃圾恰巧超出范围,它将失败。让我们看看如何故意用垃圾(负数)填充tv_nsec
:
// gcc -Wall -pthread timedwait.c -o exe <-- thank you for this
#define _OPEN_THREADS
#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_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 + 5;
t.tv_nsec = -1; // INTENTIONAL JUNK
printf("starting timedwait at %s", ctime(&T));
int err = pthread_cond_timedwait(&cond, &mutex, &t);
if (err != 0)
{
printf("pthread_cond_timeout failed: %s\n", strerror(err));
exit(EXIT_FAILURE);
}
time(&T);
printf("timedwait over at %s", ctime(&T));
return 0;
}
[当我运行此命令时-用T + 5可以确保确实可以看到等待-它立即失败:
$ ./exe
starting timedwait at Fri Nov 29 19:50:52 2019
pthread_cond_timedwait failed: Invalid argument
但是更改为t.tv_nsec = 0
会使它等待您期望的时间。
EDIT向pthread_cond_timeout
添加了特定的错误检查(对@JohnBollinger带有h / t)