问题:当向前向后设置系统时间时,sem_timedwait和pthread_cond_timedwait会出现长时间堵塞或一直堵塞的情况;
分析:sem_timedwait() 是 通过传入未来的某个时钟实现超时等待信号量的获取,具体请参考 sem_timedwait(3),当调用sem_timedwait()后,因为系统实时时钟被修改,导致 sem_timedwait() 用于计算是否达到超时时钟的基准时钟向前大幅度偏移而阻塞,sem_timedwait()这个接口就是使用系统实时时钟计算超时的。同样的问题,这种情况下pthread_cond_timedwait就不能用绝对时钟计时方式。
解决方法:除了实时时钟之外,还有一个单调递增时钟,此时钟从某一时刻开始单调递增而不会被修改,详见 clock_gettime(3)。具体实现时,使用 clock_gettime(CLOCK_MONOTONIC, &ts) 获取单调递增时钟,再基于此时钟计算超时时间。所以在会修改系统实时时钟的应用中,需要谨慎使用 sem_timedwait(),而pthread_cond_timedwait时需要相当时间方式。
测试代码和修改代码参考如下:
memset(&time, 0, sizeof(time));
clock_gettime(CLOCK_REALTIME, &time);
time.tv_sec += UD_UDSCLIENT_DIAG2_TIMEOUT;
if(sem_timedwait(&udscli_sem, &time) == 0)
{
}
当程序试图获取一个已加锁的互斥量时,pthread_mutex_timedlock互斥量原语允许绑定线程阻塞时间。pthread_mutex_timedlock函数与pthread_mutex_lock函数是基本等价的,但是在达到超时时间时,pthread_mutex_timedlock不会对互斥量进行加锁,而是返回错误码ETIMEOUT.
#include
#include
int pthread_mutex_timedlock(pthread_mutex_t mutex, const struct timespec *tsptr);
返回值:若成功,返回0;否则,返回错误编号
超时指定愿意等待的绝对时间(与相对时间对比而言,指定在时间X之前可以阻塞等待,而不是说愿意阻塞Y秒)。这个超时时间是用timespec结构来表示,它用秒和纳秒来描述时间。
#include
#include
#include
#include
int main(void)
{
int err;
struct timespec tout; //纳秒级别
struct tm *tmp;
char buf[64];
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //初始化锁
//1
pthread_mutex_lock(&lock);
printf("mutex is locked.\n");
clock_gettime(CLOCK_REALTIME, &tout);
tmp = localtime(&tout.tv_sec);
strftime(buf, sizeof(buf), "%r", tmp); //strftime(char *str, size_t maxsize, const char *fmt, struct tm *time)
//按照参数fmt所设定格式将time类型的参数格式化为日期时间信息,然后存储在字符串str中(至多maxsize 个字符)
//参考http://ganquan.info/standard-c/function/strftime
printf("Current time is %s.\n", buf);
tout.tv_sec += 10; //延迟10s
//2
err = pthread_mutex_timedlock(&lock, &tout);
clock_gettime(CLOCK_REALTIME, &tout);
tmp = localtime(&tout.tv_sec);
strftime(buf, sizeof(buf), "%r", tmp);
printf("The time is now %s\n", buf);
if(err == 0)
{
printf("mutex locked again!\n");
}
else
{
printf("Can't lock mutex again: %s\n", strerror(err));
}
return 0;
}
运行结果如下:
mutex is locked.
Current time is 09:28:00 PM.
The time is now 09:28:10 PM
Can't lock mutex again: Connection timed out
这个程序故意对它已有的互斥量进行加锁,目的是演示pthread_mutex_timedlock函数是如何工作的。