pthread_cond_timewait是线程同步函数,函数原型为:
# include pthread.hint pthread _ cond _ time wait (pthread _ cond _ t * restrict cond,pthread _ mutex _ t * restrictmu tmu t pthread_cond_timewait表示如果在abstime的时间内没有事件发生,它将超时返回,但“结构时间等待”是什么数据类型? 我该怎么用?
Unix上的时间类型:很多情况下都需要Unix时间戳,如调试日志时间戳、阻塞系统调用等待时间参数等,因此需要了解其使用方法。
Unix的时间类型根据时间精度分为以下三类:
(1) time_t )秒seconds;
)2)结构时间(微秒微秒);
(3)结构时间(纳秒nano-seconds )。
1. time_t : time系列函数包含三种数据类型:
time_t、struct tm *、char *
time_t类型是32位或64位二进制整数。 可以理解为int型。 直接打印无法获取时间。 需要转换time_t。 这里有两种方法。
第一种方式是将time_t转换为struct tm *型结构,然后将结构转换为char *型字符串并输出,使用的函数为localtime ()和asctime ); 第二种方法是将time_t直接转换为char *型,其中使用的函数是ctime ();函数原型:
# include time.h time _ ttime (time _ t * tloc ); //time函数的返回值为从1970年1月1日到现在的秒数# include time.hstructtm * gmtime (const time _ t * timep ); 结构TM *本地时间(const time _ t * timep ); struct tm {inttm_sec; inttm_min; inttm_hour; inttm_mday; inttm_mon; inttm_year; inttm_wday; inttm_yday; inttm_isdst; (; # include time.h time _ t mktime (struct TM * TM ); //反向操作:将一个struct tm *类型转换为time_t类型# include time.h char * asctime (conststruct TM * time ptr ); # include time.h char * ctime (constime _ t * timep );使用举例:
第一种形式: (time_t ) (( (char* ) ) ) ) ) ) ) ) )。
# include time.h # include stdio.hint main ({ time _ ttimep; 时间(时间); char * ret=ctime (时间); printf(%s(n )、ret ); 返回0; }输出结果:
Sun Jan 3 12:37:47 2021第二格式: (time_t ) )结构TM * (char * ) ) ) ) ) ) 65
# include time.h # include stdio.hint main ({ time _ ttimep; 时间(时间); char * ret=asctime (本地时间) timep ); printf(%s(n )、ret ); 返回0; }输出结果:
sunjan 31233603733601720212.struct timeval:timeval是获取“微秒”级别的时间。
# includesys/time.hstructtimeval { time _ ttv _ sec; /* seconds */suseconds_ttv_usec;/*微软- seconds */};函数原型:
#include sys/time.h//系统时间int gettime of day (struct timeval * TV,struct timezone *tz ); //设定系统时间intset timeo fday (conststructtime )
val *tv, const struct timeval *tz);第二个参数 timezone* 表示时区,一般情况下不使用,传入NULL即可。
使用举例:
#include <sys/time.h>#include <stdio.h>int main() {struct timeval ret;gettimeofday(&ret, NULL);printf("sec: %d, msec: %dn", ret.tv_sec, ret.tv_usec);return 0;}输出结果:
secc: 1609655357, msec: 192692 3. struct timespec :struct timespec 是获取纳秒级别(nano-seconds)的时间类型。
函数原型:
#include <time.h>struct timespec {time_ttv_sec;/* seconds */longtv_nsec;/* nano-seconds */}; #include <time.h>int clock_gettime(clockid_t clk_id, struct timespec *res);int clock_settime(clockid_t clk_id, const struct timespec *tp);参数clockid_t 表示时钟类型,Linux提供下面这些时钟类型:
CLOCK_REALTIME//从1970年1月1日至今的时间CLOCK_REALTIME_COARSECLOCK_MONOTONIC//从系统启动到现在所流逝的时间,它是单调递增的,CPU每tick一次则计数器+1CLOCK_MONOTONIC_COARSECLOCK_BOOTTIMECLOCK_PROCESS_CPUTIME_IDCLOCK_TRHEAD_CPUTIME_ID使用举例:
#include <time.h>#include <stdio.h>int main() {struct timespec res;clock_gettime(CLOCK_REALTIME, &res);printf("seconds: %ld, nano-seconds: %lun", res.tv_sec, res.tv_nsec);return 0;}输出结果:
seconds: 1609656874, nano-seconds: 434777000 在 pthread_cond_timewait 中 timespec 使用: void *workerThread(void *arg) {struct timespec ts;clock_gettime(CLOCK_REALTIME, &ts);ts->tv_sec += pool->linger;if(pthread_cond_timewait(&cond, &mutex, &ts) == ETIMEOUT) {//pthread_exit();}}设置 cond 的超时时间,就是 clock_gettime 先获取当前时间,然后加上超时等待时间后,再传入到 pthread_cond_timewait 中。
localtime 与localtime_r : 线程安全 与 非线程安全: char *asctime(const struct tm *tm);char *asctime_r(const struct tm *tm, char *buf); //返回值保存在*buf中char *ctime(const time_t *time_p);char *ctime_r(const time_t *time_p, char *buf);struct tm *localtime(const time_t *timep);struct tm *localtime_r(const time_t *timep, struct tm *result);为什么 localtime 不是线程安全的,而 localtime_r 是线程安全的?
localtime的使用方式是这样的:
struct tm *res = localtime(&timep); //将time_t类型的timep转换为 struct tm * 类型可以看到只需要一个指针 *res,而localtime的返回值必定是保存在一块内存中的,但是我们并没有申请内存,这是因为localtime函数自动的申请了一块内存,*res指针指示指向了这块我们看不到的内存(在内核管理)。
此时,如果有另一个线程也调用了 localtime函数,那么这块保存时间的“隐式”内存中的值就会被覆盖,*res中的值就会不准确,此为“非线程安全”;
而localtime_r(&timep, &result); 是把返回值保存在参数result中,这块内存是需要用户手动分配的,此为“线程安全”。
==> 由此引申出“线程安全”的一个注意事项:
当需要调用到系统调用时,不同的线程应各自申请内部保存各自的返回值。
参考内容:
《C++时间类型详解 time_t》
https://www.runoob.com/w3cnote/cpp-time_t.html
《Linux时间类型、函数和休眠函数》
https://blog.csdn.net/luotuo44/article/details/39374759
《localtime、localtime_s、localtime_r的使用》
https://blog.csdn.net/u010087712/article/details/50731222