小程序商城需要icp许可证吗福州百度快速优化

张小明 2026/1/10 18:45:50
小程序商城需要icp许可证吗,福州百度快速优化,万州做网站,怎么开发微信网站一、前言前面我们学习了线程同步的概念和互斥锁的适用#xff0c;本次我们来学习死锁的相关知识。二、死锁2.1、死锁的定义死锁是指多个线程或者进程因竞争共享资源#xff08;如互斥锁#xff09;#xff0c;互相等待对方释放资源#xff0c;导致所有线程都陷入 “永久阻…一、前言前面我们学习了线程同步的概念和互斥锁的适用本次我们来学习死锁的相关知识。二、死锁2.1、死锁的定义死锁是指多个线程或者进程因竞争共享资源如互斥锁互相等待对方释放资源导致所有线程都陷入 “永久阻塞” 的状态且无外力干预无法自行解除。举个通俗点的例子就是线程 A 持有锁 1等待获取锁 2线程 B 持有锁 2等待获取锁 1两者都不释放已持有的锁互相等待程序彻底卡死。如下图所示2.2、死锁的必要条件死锁的发生必须同时满足以下 4 个条件只要打破其中任意一个死锁就不会发生必要条件通俗解释互斥条件资源如互斥锁只能被一个线程持有其他线程无法共享互斥锁的核心特性占有且等待条件线程持有一个资源的同时主动请求获取另一个资源不释放已持有的资源不可抢占条件线程持有的资源不能被强制剥夺只能由线程主动释放互斥锁无 “强制解锁” 接口循环等待条件多个线程形成 “资源请求闭环”如 A 等 B 的资源B 等 C 的资源C 等 A 的资源2.3、典型示例1、自己锁自己输入以下代码#include stdio.h #include pthread.h #include unistd.h int number; pthread_mutex_t mutex; void *myfun1(void *arg) { for(int i0;i10000;i) { //lock pthread_mutex_lock(mutex);//两把锁 pthread_mutex_lock(mutex); int ret; ret number; ret; number ret; printf(fun1 is %ld,number is %d\n,pthread_self(),number); //ulock pthread_mutex_unlock(mutex); usleep(10); } } void *myfun2(void *arg) { for(int i0;i10000;i) { //lock pthread_mutex_lock(mutex);//两把锁 pthread_mutex_lock(mutex); int ret; ret number; ret; number ret; printf(fun2 is %ld,number is %d\n,pthread_self(),number); //ulock pthread_mutex_unlock(mutex); usleep(10); } } int main() { //init mutex pthread_mutex_init(mutex,NULL); pthread_t pthid1; pthread_t pthid2; pthread_create(pthid1,NULL,myfun1,NULL); pthread_create(pthid2,NULL,myfun2,NULL); pthread_join(pthid1,NULL); pthread_join(pthid2,NULL); //kill mutex pthread_mutex_destroy(mutex); return 0; }适用gcc编译器进行编译运行结果如下可以发现什么东西都没有打印出来这就是死锁了普通互斥锁的核心规则是同一线程不能对同一个互斥锁重复加锁—— 第一次加锁后锁的「持有者」是当前线程锁状态为「已锁定」当线程再次调用pthread_mutex_lock时会阻塞等待锁被释放但锁的持有者正是自己因此线程会永久阻塞死锁无法继续执行后续代码。2、交叉加锁输入以下代码#include stdio.h #include pthread.h #include unistd.h pthread_mutex_t mutex1 PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mutex2 PTHREAD_MUTEX_INITIALIZER; // 线程1先加锁1再尝试加锁2 void *thread1(void *arg) { pthread_mutex_lock(mutex1); printf(线程1持有锁1等待锁2\n); sleep(1); // 故意让出CPU让线程2持有锁2 pthread_mutex_lock(mutex2); // 阻塞等待线程2释放锁2 // 临界区不会执行到 printf(线程1获取所有锁\n); pthread_mutex_unlock(mutex2); pthread_mutex_unlock(mutex1); return NULL; } // 线程2先加锁2再尝试加锁1 void *thread2(void *arg) { pthread_mutex_lock(mutex2); printf(线程2持有锁2等待锁1\n); sleep(1); // 故意让出CPU让线程1持有锁1 pthread_mutex_lock(mutex1); // 阻塞等待线程1释放锁1 // 临界区不会执行到 printf(线程2获取所有锁\n); pthread_mutex_unlock(mutex1); pthread_mutex_unlock(mutex2); return NULL; } int main() { pthread_t tid1, tid2; pthread_create(tid1, NULL, thread1, NULL); pthread_create(tid2, NULL, thread2, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); return 0; }编译并运行运行结果如下执行结果是两个线程互相等待程序卡死无后续输出。2.4、如何避免死锁1、固定加锁顺序给所有锁资源分配唯一编号所有线程必须先加小编号的锁再加大号的锁彻底避免 “你等我、我等你” 的闭环。比如通过下面的代码来修复交叉加锁#include pthread.h #include stdio.h // 步骤1给锁编号mutex11mutex22必须先加1再加2 pthread_mutex_t mutex1 PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mutex2 PTHREAD_MUTEX_INITIALIZER; // 线程1按“mutex1 → mutex2”加锁 void *thread1(void *arg) { pthread_mutex_lock(mutex1); // 先加小编号锁 printf(线程1持有mutex1等待mutex2\n); pthread_mutex_lock(mutex2); // 再加大号锁 // 临界区操作 printf(线程1获取所有锁执行临界区\n); // 解锁顺序先解大号锁再解小编号锁逆序 pthread_mutex_unlock(mutex2); pthread_mutex_unlock(mutex1); return NULL; } // 线程2严格遵守同一顺序mutex1 → mutex2 void *thread2(void *arg) { pthread_mutex_lock(mutex1); // 先加小编号锁关键不再先加mutex2 printf(线程2持有mutex1等待mutex2\n); pthread_mutex_lock(mutex2); // 再加大号锁 // 临界区操作 printf(线程2获取所有锁执行临界区\n); pthread_mutex_unlock(mutex2); pthread_mutex_unlock(mutex1); return NULL; } int main() { pthread_t tid1, tid2; pthread_create(tid1, NULL, thread1, NULL); pthread_create(tid2, NULL, thread2, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); return 0; }运行结果如下这样就修复了交叉加锁的问题。2、一次性获取所有锁线程在执行临界区前尝试一次性获取所有需要的锁如果有任何一个锁拿不到就释放已拿到的所有锁重试而非 “拿着一个等另一个”。如下代码所示#include stdio.h #include pthread.h #include unistd.h // 两个需要同时获取的锁 pthread_mutex_t m1 PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t m2 PTHREAD_MUTEX_INITIALIZER; // 一次性获取两个锁核心逻辑 int lock_both(pthread_mutex_t *a, pthread_mutex_t *b) { while (1) { // 1. 非阻塞尝试加锁a if (pthread_mutex_trylock(a) ! 0) { usleep(10); continue; } // 2. 非阻塞尝试加锁b失败则释放a if (pthread_mutex_trylock(b) 0) return 0; // 成功拿到两个锁 pthread_mutex_unlock(a); // 释放已拿到的a避免占有且等待 usleep(10); // 重试前休眠降低CPU占用 } } // 线程函数演示一次性加锁操作 void *thread_func(void *arg) { int id *(int *)arg; // 一次性获取m1和m2避免交叉加锁死锁 lock_both(m1, m2); // 临界区操作共享资源 printf(线程%d同时拿到m1和m2执行临界区\n, id); // 解锁成对释放 pthread_mutex_unlock(m2); pthread_mutex_unlock(m1); return NULL; } int main() { int id1 1, id2 2; pthread_t t1, t2; // 创建两个线程模拟并发加锁 pthread_create(t1, NULL, thread_func, id1); pthread_create(t2, NULL, thread_func, id2); // 等待线程结束 pthread_join(t1, NULL); pthread_join(t2, NULL); // 销毁锁 pthread_mutex_destroy(m1); pthread_mutex_destroy(m2); return 0; }编译运行结果如下可以看到这样也可以执行不会死锁。3、适用trylock回退重试如两个线程需要同时操作m1和 m2两个锁若用普通 pthread_mutex_lock 交叉加锁会死锁用trylock非阻塞尝试失败则释放已拿的锁重试即可避免。 代码如下所示#include stdio.h #include pthread.h #include unistd.h // 两个共享锁 pthread_mutex_t m1 PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t m2 PTHREAD_MUTEX_INITIALIZER; // 线程函数用trylock避免死锁 void *thread_func(void *arg) { int id *(int *)arg; int ret1, ret2; while (1) { // 1. 非阻塞尝试加锁m1trylock拿不到立即返回EBUSY不阻塞 ret1 pthread_mutex_trylock(m1); if (ret1 ! 0) { usleep(10); // 拿不到m1短暂休眠后重试 continue; } // 2. 非阻塞尝试加锁m2 ret2 pthread_mutex_trylock(m2); if (ret2 0) { // 成功拿到两个锁执行临界区 printf(线程%d成功拿到m1m2执行操作\n, id); // 解锁成对释放 pthread_mutex_unlock(m2); pthread_mutex_unlock(m1); break; // 完成操作退出循环 } else { // 拿到m1但没拿到m2 → 释放m1避免“占有且等待”死锁条件 pthread_mutex_unlock(m1); usleep(10); // 重试前休眠降低CPU占用 } } return NULL; } int main() { int id1 1, id2 2; pthread_t t1, t2; // 创建两个线程模拟并发请求锁交叉加锁场景 pthread_create(t1, NULL, thread_func, id1); pthread_create(t2, NULL, thread_func, id2); // 等待线程结束 pthread_join(t1, NULL); pthread_join(t2, NULL); // 销毁锁 pthread_mutex_destroy(m1); pthread_mutex_destroy(m2); return 0; }编译并运行结果如下可以看到这样也可以执行不会死锁。2.5、死锁的注意事项1、死锁一旦发生程序无法自行恢复只能重启2、即使加锁顺序正确若锁持有时间过长如锁内调用sleep/read死锁概率会大幅增加
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

做网站公司哪家公司网站想换一个空间怎么办

在软件开发过程中,自动化测试是提高软件质量和稳定性的重要手段之一。Python作为一种简洁而强大的编程语言,为自动化测试提供了丰富的工具和库。本文将介绍几个常见的自动化测试案例,并提供详细的Python代码示例,帮助您更好地理解…

张小明 2026/1/9 14:38:46 网站建设

外发加工是否有专门的网站视觉差网站制作

5分钟快速掌握MPC Video Renderer:终极视频渲染器配置指南 【免费下载链接】VideoRenderer RTX HDR modded into MPC-VideoRenderer. 项目地址: https://gitcode.com/gh_mirrors/vid/VideoRenderer MPC Video Renderer是一款免费开源的DirectShow视频渲染器&…

张小明 2026/1/9 18:44:54 网站建设

网络营销试题库及答案汕头百度seo电话

ViGEmBus是一款强大的Windows内核驱动,专门用于虚拟游戏控制器功能实现。通过本指南,您将掌握这款虚拟控制器驱动的核心功能、安装配置和实战应用技巧,轻松实现游戏输入设备的完美适配。 【免费下载链接】ViGEmBus Windows kernel-mode drive…

张小明 2026/1/9 7:19:14 网站建设

网站建设收费价目表哪家网站做的比较好

在心理健康日益受到全社会关注的当下,完善的心理服务基础设施已成为现代组织与社区不可或缺的组成部分。北京朗心致远科技有限公司,作为专注于 心理健康场室建设 与 智能心理设备 研发的专业机构,旨在为教育、企事业单位、医疗社区、司法武警…

张小明 2026/1/9 11:11:54 网站建设

网站规划与建设评分标准wordpress简码

精通pkNX:Switch宝可梦游戏数据定制与随机化全攻略 【免费下载链接】pkNX Pokmon (Nintendo Switch) ROM Editor & Randomizer 项目地址: https://gitcode.com/gh_mirrors/pk/pkNX pkNX作为一款专业的Switch宝可梦游戏ROM编辑器,为玩家提供了…

张小明 2026/1/9 1:46:15 网站建设