当线程试图获取一个已加锁的互斥量时,pthread_mutex_timedlock
互斥量原语允许绑定线程阻塞时间。pthread_mutex_timedlock
函数与pthread_mutex_lock
是基本等价的,但是在达到超时时间值时,pthread_mutex_timedlock
不会对互斥量进行加锁,而是返回错误码ETIMEDOUT
。
#include <pthread.h>
#include <time.h>
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,const struct timespec *restrict tsptr);
//返回值:若成功,返回0;否则,返回错误编号
超时指定愿意等待的绝对时间(与相对时间对比而言,指定在时间X之前可以阻塞等待,而不是说愿意阻塞Y秒)。这个超时时间是用timespec
结构来表示的,它用秒和纳秒来描述时间。
实例
图11-13给出了如何用pthread_mutex_timedlock
避免永久阻塞。
#include "apue.h"
#include <pthread.h>
int
main(void)
{
int err;
struct timespec tout;
struct tm *tmp;
char buf[64];
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
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);
printf("current time is %s\n", buf);
tout.tv_sec += 10; /* 10 seconds from now */
/* caution: this could lead to deadlock */
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));
exit(0);
}
图11-13 使用pthread_mutex_timedlock
图11-13中的程序运行结果输出如下:
$ ./a.out
mutex is locked
current time is 11:41:58 AM
the time is now 11:42:08 AM
can’t lock mutex again: Connection timed out
这个程序故意对它已有的互斥量进行加锁,目的是演示pthread_mutex_timedlock
是如何工作的。不推荐在实际中使用这种策略,因为它会导致死锁。
注意,阻塞的时间可能会有所不同,造成不同的原因有多种:开始时间可能在某秒的中间位置,系统时钟的精度可能不足以精确到支持我们指定的超时时间值,或者在程序继续运行前,调度延迟可能会增加时间值。
Mac OS X 10.6.8还没有支持
pthread_mutex_timedlock
,但是FreeBSD 8.0、Linux 3.2.0以及Solaris 10支持该函数,虽然Solaris仍然把它放在实时库librt中。Solaris 10还提供了另一个使用相对超时时间的函数。