UNIX(编程-线程处理):07---互斥量与互斥量锁(pthread_mutex_t)
一、互斥量概念
二、互斥变量(pthread_mutex_t)
- 互斥量数据类型:pthread_mutex_t
三、互斥变量的初始化与释放
使用互斥变量之前需要对其进行初始化,根据互斥变量类型不同,分为:
①静态初始化:
- 方式一:可以把它设置为常量PTHREAD_MUTEX_INITIALIZER
- 方式二:通过pthread_mutex_init函数
②动态初始化:(例如:通过malloc函数申请内存的)
- 只能通过pthread_mutex_init
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destory(pthread_mutex_t *mutex);
// 返回值:成功返回0,否则返回错误编号
pthread_mutex_init:对互斥量进行初始化
- 参数1: 需要初始化互斥量
- 参数2:初始化时互斥量的属性。如果使用默认属性,此处填NULL
pthread_mutex_destory:如果动态分配互斥量(如使用到malloc),那么释放内存前需要调用此函数
- 参数:释放的互斥量
四、互斥量的加锁与解锁
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
// 返回值:成功返回0,否则返回错误编号
- pthread_mutex_lock:对互斥量进行加锁。如果互斥量已经上锁,调用线程将阻塞到互斥量被解锁
- pthread_mutex_unlock:对互斥量进行解锁
- pthead_mutex_trylock:对互斥量进行尝试加锁(非阻塞)。如果互斥量处于未加锁状态,那么pthead_mutex_trylock就会锁住这个互斥量;如果此锁处于加锁状态,那么pthead_mutex_trylock就出错返回EBUSY,并且不会阻塞
例如去食堂吃饭:如果食堂人太多(加锁),pthread_mutex_lock就会排队等待(阻塞);pthead_mutex_trylock是去食堂尝试(try)一下,如果人多就不排队(不阻塞)直接退出
五、演示案例
struct foo {
int f_count;
pthread_mutex_t f_lock;
int f_id;
};
struct foo *foo_alloc(int id)
{
struct foo *fp;
if ((fp == malloc(sizeof(struct foo))) != NULL) {
fp->f_count = 1;
fp->f_id = id;
if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
free(fp);
fp = NULL;
}
}
return fp;
}
void foo_hold(struct foo *fp)
{
pthread_mutex_lock(&fp->f_lock);
fp->f_count++;
pthread_mutex_unlock(&fp->f_lock);
}
void foo_rele(struct foo *fp)
{
pthread_mutex_lock(&fp->f_lock);
if (--fp->f_count == 0) {
pthread_mutex_unlock(&fp->f_lock);
pthread_mutex_destory(&fp->f_lock);
free(fp);
} else {
pthread_mutex_unlock(&fp->f_lock);
}
}
六、超时互斥锁(pthread_mutex_timedlock)
#include <pthread.h>
#include <time.h>
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,const struct timespec *restrict tsptr);
// 返回值:成功返回0,否则返回错误编号.
- 功能:当线程试图获取一个已加锁的互斥量时,pthread_mutex_timedlock允许绑定线程阻塞时间
- 特点:pthread_mutex_timedlock与pthread_mutex_lock是基本等价的,但是在达到超时时间值时,pthread_mutex_timedlock不会对互斥量进行加锁,而是返回错误码ETIMEDOUT
注意:
- 演示案例:下面给出了pthread_mutex_timedlock避免永久阻塞
#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); }
运行结果