linux 线程 死锁
死锁:🔴⚫🟤🟣🔵🟢🟡🟠
有时,一个线程需要同时访问两个或更多不同的共享资源,而每个资源又都由不同的互斥量管理。当超过一个线程加锁同一组互斥量时,就有可能发生死锁。
两个或两个以上的进程在执行过程中,因争夺共享资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。
死锁的几种场景:
🔴 忘记释放锁
🔴 重复加锁
🔴 多线程多锁,抢占锁资源(互相等待 A持有资源1 等待资源2 B持有资源2 等待资源1)
主代码:
1 #include <stdio.h> 2 #include <pthread.h> 3 #include <unistd.h> 4 int tickets = 500; 5 //创建一个互斥量 6 pthread_mutex_t mutex;//全局变量 7 void * sellticket(void * arg) 8 { 9 //A B C A先进 然后加锁 执行while 解锁 B C A都有机会执行代码区 有解锁后才可以进行执行 10 //卖票 11 while(1) 12 { 13 //加锁 14 pthread_mutex_lock(&mutex); 15 if(tickets > 0) 16 { 17 usleep(6000); 18 printf("%ld 正在卖第 %d 张门票\n",pthread_self(),tickets); 19 tickets--; 20 } 21 else 22 { 23 // = 0 解锁 24 pthread_mutex_unlock(&mutex); 25 break; 26 } 27 //解锁 28 pthread_mutex_unlock(&mutex); 29 } 30 return NULL; 31 } 32 int main() 33 { 34 //初始化 35 pthread_mutex_init(&mutex, NULL); 36 //创建3个子线程 37 pthread_t tid1,tid2,tid3; 38 pthread_create(&tid1, NULL, sellticket, NULL); 39 pthread_create(&tid2, NULL, sellticket, NULL); 40 pthread_create(&tid3, NULL, sellticket, NULL); 41 //回收子线程的资源, 阻塞 42 pthread_join(tid1,NULL); 43 pthread_join(tid2,NULL); 44 pthread_join(tid3,NULL); 45 pthread_exit(NULL);//退出主线程 46 //释放互斥量资源 47 pthread_mutex_destroy(&mutex); 48 return 0; 49 }
1.忘记释放锁:
1 void * sellticket(void * arg) 2 { 3 while(1) 4 { 5 pthread_mutex_lock(&mutex); 6 if(tickets > 0) 7 { 8 usleep(6000); 9 printf("%ld 正在卖第 %d 张门票\n",pthread_self(),tickets); 10 tickets--; 11 } 12 else 13 { 14 // = 0 解锁 15 pthread_mutex_unlock(&mutex); 16 break; 17 } 18 //解锁 19 //pthread_mutex_unlock(&mutex);//忘记释放锁 会导致死锁,程序不正常执行 20 } 21 return NULL; 22 }
2.重复加锁
void * sellticket(void * arg) { while(1) { pthread_mutex_lock(&mutex);//加锁 pthread_mutex_lock(&mutex);//重复加锁 if(tickets > 0) { usleep(6000); printf("%ld 正在卖第 %d 张门票\n",pthread_self(),tickets); tickets--; } else { pthread_mutex_unlock(&mutex);// = 0 解锁 break; } pthread_mutex_unlock(&mutex);//解锁 pthread_mutex_unlock(&mutex);//重复解锁 但用不到 程序阻塞 } return NULL; }
3.多线程多锁:
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <pthread.h> 4 #include <string.h> 5 //创建两个互斥量 6 pthread_mutex_t mutex1,mutex2; 7 void * workA(void * arg)//arg:argument 传参 8 { 9 pthread_mutex_lock(&mutex1); 10 sleep(1); 11 pthread_mutex_lock(&mutex2); 12 printf("workA...\n"); 13 pthread_mutex_unlock(&mutex2); 14 pthread_mutex_unlock(&mutex1); 15 return NULL; 16 } 17 void * workB(void * arg) 18 { 19 pthread_mutex_lock(&mutex2); 20 sleep(1); 21 pthread_mutex_lock(&mutex1); 22 printf("workB...\n"); 23 pthread_mutex_unlock(&mutex1); 24 pthread_mutex_unlock(&mutex2); 25 return NULL; 26 } 27 int main() 28 { 29 // 初始化两个互斥量 30 pthread_mutex_init(&mutex1,NULL); 31 pthread_mutex_init(&mutex2,NULL); 32 //创建2个子线程 33 pthread_t tid1,tid2; 34 pthread_create(&tid1,NULL,workA,NULL); 35 pthread_create(&tid2,NULL,workB,NULL); 36 //回收子线程资源 37 pthread_join(tid1,NULL); 38 pthread_join(tid2,NULL); 39 //释放互斥量资源 40 pthread_mutex_destroy(&mutex1); 41 pthread_mutex_destroy(&mutex2); 42 return 0; 43 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)