死锁概念
死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所占用的不会释放的资源而处于一种永久等待状态。
死锁的四个条件
互斥条件:一个资源每次只能被一个执行流使用。
请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不释放。
不剥夺条件:一个执行流已获得的资源,在未使用完之前,不可强行剥夺。
循环等待条件:若干执行流之间形成一种头尾相接的循环等待资源的关系。
死锁如何避免
- 破坏死锁的四个必要条件
- 加锁顺序一致
- 避免锁未释放的情景
- 资源一次性分配
此外还有避免死锁的算法—银行家算法,没有深入了解,这里不做讨论。
直接上代码
//这是一个练习死锁的代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>
int ticket = 100;
pthread_mutex_t mutex1;
pthread_mutex_t mutex2;
void* route1(void* arg)
{
char* id = (char*)arg;
while(1)
{
pthread_mutex_lock(&mutex1);
if(ticket>0)
{
sleep(1);
printf("%s sells ticket:%d\n",id,ticket);
ticket--;
}
pthread_mutex_lock(&mutex2);
if(ticket>0)
{
sleep(1);
printf("%s sells ticket:%d\n",id,ticket);
ticket--;
}
pthread_mutex_unlock(&mutex1);
pthread_mutex_unlock(&mutex2);
sleep(3);
}
}
void* route2(void* arg)
{
char* id = (char*)arg;
while(1)
{
pthread_mutex_lock(&mutex2); // 加锁顺序不一致时,会构成死锁
//pthread_mutex_lock(&mutex1); //解决方法
if(ticket>0)
{
sleep(1);
printf("%s sells ticket:%d\n",id,ticket);
ticket--;
}
pthread_mutex_lock(&mutex1); // 加锁顺序不一致时,会构成死锁。
//pthread_mutex_lock(&mutex2); //解决方法
if(ticket>0)
{
sleep(1);
printf("%s sells ticket:%d\n",id,ticket);
ticket--;
}
pthread_mutex_unlock(&mutex1);
pthread_mutex_unlock(&mutex2);
sleep(3);
}
}
int main()
{
pthread_t t1,t2;
pthread_create(&t1,NULL,route1,"thread 1");
pthread_create(&t2,NULL,route2,"thread 2");
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex1);
pthread_mutex_destroy(&mutex2);
return 0;
}
死锁运行结果:程序会在这里卡死,因为构成了死锁。
当我们改变加锁顺序之后,运行结果如下:运行结果正确。