本文共 4048 字,大约阅读时间需要 13 分钟。
互斥锁的底层是一个互斥量,而互斥量的本质是一个计数器,计数器的取值只有两种,一种是1,一种是0。1表示当前临界资源可以被访问,0表示当前临界资源不可以被访问。
获取/释放互斥锁的逻辑:
1.调用加锁接口,加锁接口内部判断计数器的值是否为1,如果为1,则能访问,并且如果加锁成功之后,就会将计数器的值从1变为0,如果为0,则不能访问。 2.调用解锁逻辑,计数器的值从0变成1,表示资源可用。加锁:
寄存器和内存当中的计数器的值进行交换,判断寄存器的当中的值是否为1,如果为1,则能够加锁,反之不能。初始化互斥锁变量
互斥锁的类型:pthread_mutex_tpthread_mutex_t mutex = PTHREAD_MUTRX_INITIALIZER
这是一个宏定义,本质上包含多个值vim /user/include/pthread.hvim /usr/include/bits/pthreadtypes.h
pthread_mutex_init函数
1.阻塞加锁接口:pthread_mutex_lock函数
2.非阻塞加锁接口:pthread_mutex_trylock函数
3.带有超时时间的加锁接口:pthread_mutex_timedlock
超时时间内,如果没有获得互斥锁,则返回,超时时间内,如果获取了互斥锁也直接返回。
注意: 带有超时时间的加锁接口还需要引入头文件time.hpthread_mutex_unlock函数
pthread_mutex_destroy
在创建工作线程之前,进行初始化互斥锁。
在执行流访问临界资源之前进行加锁操作。
注意: 一个执行流加锁成功之后,再去获取互斥锁,该执行流也会阻塞。加锁之后一定要记得解锁,否则就会导致死锁。在执行流所有有可能退出的地方进行解锁。
在所有使用该互斥锁的线程全部退出之后,就可以释放该互斥锁了。
#include#include #include #define THREAD_NUM 2int g_tickets = 100000;pthread_mutex_t my_lock;void* MyThreadStart(void* arg){ while(1) { pthread_mutex_lock(&my_lock); if(g_tickets > 0) { printf("i have %d, i am %p\n", g_tickets, pthread_self()); g_tickets--; } else { pthread_mutex_unlock(&my_lock); pthread_exit(NULL); } pthread_mutex_unlock(&my_lock); } return NULL;}int main(){ pthread_mutex_init(&my_lock, NULL); pthread_t tid[THREAD_NUM]; for(int i = 0; i < THREAD_NUM; i++) { int ret = pthread_create(&tid[i], NULL, MyThreadStart, NULL); if(ret < 0) { perror("pthread_create"); return 0; } } for(int i = 0; i < THREAD_NUM; i++) { pthread_join(tid[i], NULL); } pthread_mutex_destroy(&my_lock); printf("phread_join end...\n"); return 0;}
简单的定义:当一个执行流获取到互斥锁之后,并没有进行解锁,就会导致其他执行流由于获取不到锁资源而进行阻塞,我们将这个现象称之为死锁。
复杂的定义:当线程A获取到互斥锁1,线程B获取到互斥锁2的时候,线程A和线程B同时还想获取对方手中的锁(线程A还想获取互斥锁2,线程B还想获取互斥锁1),此时就会导致死锁。#include#include #include pthread_mutex_t lock_1;pthread_mutex_t lock_2;void* MyThread_A(void* arg){ pthread_mutex_lock(&lock_1); sleep(2); pthread_mutex_lock(&lock_2); return NULL;}void* MyThread_B(void* arg){ pthread_mutex_lock(&lock_2); sleep(2); pthread_mutex_lock(&lock_1); return NULL;}int main(){ pthread_mutex_init(&lock_1, NULL); pthread_mutex_init(&lock_2, NULL); pthread_t tid_A, tid_B; pthread_create(&tid_A, NULL, MyThread_A, NULL); pthread_create(&tid_B, NULL, MyThread_B, NULL); pthread_join(tid_A, NULL); pthread_join(tid_A, NULL); pthread_mutex_destroy(&lock_1); pthread_mutex_destroy(&lock_2); return 0;}
1.执行死锁的代码
1.不可剥夺:执行流获取了互斥锁之后,除了自己主动释放锁,其他执行流不能解释该互斥锁
2.循环等待 3.互斥条件:一个互斥锁只能被一个执行流在同一时刻拥有 4.请求与保持:“吃着碗里瞧着锅里”1.破坏必要条件:循环等待或者请求与保持
2.加锁顺序一致 3.避免锁没有被释放 4.资源一次性分配1.死锁检测算法
2.银行家算法转载地址:http://soxcz.baihongyu.com/