互斥锁(使用过程及应用场景)
日期: 2020-02-24 分类: 个人收藏 388次阅读
互斥锁使用流程
定义互斥锁变量
pthread_mutex_t:互斥锁变量的类型
例:pthread_mutex_t mutex
初始化互斥锁变量
int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr);
muter:互斥锁变量,传参数的时候,传入互斥锁变量的地址
attr:互斥锁属性,一般情况下,我们都不需要关心,直接设置为 NULL
pthread_mutex_t mutex = PTHREAD_MUTEX_INTIALIZER;
PTHREAD_MUTEX_INTIALIZER:宏定义,里面对结构体进行可宏定义,使用这种方式进行初始化的时候,其实是将结构体当中变量的值复制给互斥锁变量
加锁
int pthread_mutex_lock(pthread_mutex_t* mutex);
mutex:互斥锁变量,传参数的时候,传入互斥锁变量的地址
使用该接口进行加锁的时候
如果临界资源可用,意味着互斥锁变量当中计数器的值为 1,可以进行加锁,对计数器的值进行减 1操作,加锁成功,执行流继续向下执行
如果临界资源不可用,阻塞等待,执行流不会继续向下执行
int pthread_mutex_trylock(pthread_mutex_t* mutex);
mutex:互斥锁变量,使用的时候,传入互斥锁变量的地址
如果临界资源可用,意味着互斥锁变量当中计数器的值为 1,可以进行加锁,对计数器的值进行减 1操作,加锁成功,执行流继续向下执行
如果临界资源不可用,不会进行阻塞等待,pthread_mutex_trylock 加锁失败,返回 BUSY(拿不到锁资源)
int pthread_mutex_timedlock(pthread_mutex_t* mutex, const struct timespec* abs_timeout);
mutex:互斥锁变量
abs_timeout:加锁的超时时间
当超过加锁的超时时间之后,还没有获取到互斥锁,就报错返回,不会再进行阻塞等待,返回 ETIMEOUT
struct timespec 当中有两个参数,第一个参数是秒,第二个参数为纳秒
解锁
int pthread_mutex_nulock(pthread_mutex_t* mutex);
mutex:互斥锁变量,使用的时候,传入互斥锁变量的地址
三种加锁方式都可以用这种方式解锁
销毁
int pthread_mutex_destroy(pthread_mutex_t* mutex);
mutex:互斥锁变量,使用的时候,传入互斥锁变量的地址
如果不调用销毁接口,会造成内存泄漏
互斥锁加锁解锁示意
互斥锁应用
抢票程序,需要考虑四个问题:
- 初始化位置
创建线程之前 - 加锁位置
访问资源之前 - 未解锁的后果
造成所有想要加该锁的线程都进入阻塞状态,这也是死锁之一的情况 - 解锁位置
在所有有可能退出的地方都需要进行解锁
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
int ticket = 100;
pthread_mutex_t mutex;
void *route(void *arg) {
char *id = (char*)arg;
while ( 1 ) {
pthread_mutex_lock(&mutex);//加锁位置
if ( ticket > 0 ) {
usleep(1000);
printf("%s sells ticket:%d\n", id, ticket);
ticket--;
pthread_mutex_unlock(&mutex);//解锁位置
// sched_yield(); 放弃CPU
} else {
pthread_mutex_unlock(&mutex);//解锁位置
break;
}
}
}
int main( void )
{
pthread_t t1, t2, t3, t4;
pthread_mutex_init(&mutex, NULL);//初始化位置
pthread_create(&t1, NULL, route, "thread 1");
pthread_create(&t2, NULL, route, "thread 2");
pthread_create(&t3, NULL, route, "thread 3");
pthread_create(&t4, NULL, route, "thread 4");
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
pthread_join(t4, NULL);
pthread_mutex_destroy(&mutex);//销毁位置
}
精华推荐