3d网站开发,网站一般在哪里找,互联网公司花名大全男,仙居微信网站开发一、互斥锁#xff1a;临界资源的排他性访问
1.1 核心概念
#xff08;1#xff09;临界资源
多线程中会被读写操作的共享资源#xff0c;常见类型#xff1a;
全局变量、静态变量#xff1b;文件、设备#xff08;如串口、网卡#xff09;#xff1b;其他可被多线…一、互斥锁临界资源的排他性访问1.1 核心概念1临界资源多线程中会被读写操作的共享资源常见类型全局变量、静态变量文件、设备如串口、网卡其他可被多线程访问的共享内存 / 句柄。2排他性访问同一时刻仅允许一个线程对临界资源进行读写操作 —— 这是互斥锁的核心目标。3为什么需要互斥多线程并发执行时代码是「穿插调度」的。以简单的a为例c运行a; // 看似一行代码汇编至少分3步 // 1. 从内存读取a的值到寄存器 // 2. 寄存器中a的值1 // 3. 寄存器值写回内存a。若线程 1 执行完前 2 步后被调度切走线程 2 执行完整 3 步再切回线程 1 执行第 3 步 —— 最终a只加了 1 次而非预期的 2 次导致数据一致性错误。互斥锁的作用就是将这段代码变成「原子操作」加锁后这段代码必须在一次线程调度中完整执行不可被打断。1.2 互斥锁的使用步骤互斥锁的生命周期遵循「定义→初始化→加锁→解锁→销毁」的固定流程缺一不可。1核心函数POSIX 标准操作函数原型关键说明定义pthread_mutex_t mutex;声明互斥锁变量全局 / 局部均可需保证所有线程可见初始化int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);attr 传 NULL 表示默认属性成功返回 0失败返回非 0加锁int pthread_mutex_lock(pthread_mutex_t *mutex);加锁失败则阻塞等待其他线程解锁成功返回 0解锁int pthread_mutex_unlock(pthread_mutex_t *mutex);必须与加锁线程为同一个成功返回 0销毁int pthread_mutex_destroy(pthread_mutex_t *mutex);锁未解锁时销毁会报错成功返回 02核心规则加锁和解锁必须由同一个线程执行临界区加锁→解锁之间的代码必须「短小精悍」禁止在临界区中执行sleep、IO 等耗时操作临界区代码越短多线程并发效率越高。3基础示例互斥锁保护全局变量c运行#include stdio.h #include pthread.h #include unistd.h int a 0; pthread_mutex_t mutex; void* th_func(void* arg) { for (int i 0; i 10000; i) { pthread_mutex_lock(mutex); // 加锁 a; // 临界区仅一行原子操作 pthread_mutex_unlock(mutex); // 解锁 } return NULL; } int main() { pthread_t tid1, tid2; pthread_mutex_init(mutex, NULL); // 初始化锁 pthread_create(tid1, NULL, th_func, NULL); pthread_create(tid2, NULL, th_func, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_mutex_destroy(mutex); // 销毁锁 printf(最终a的值%d\n, a); // 预期输出20000 return 0; }二、信号量带顺序的同步访问2.1 核心概念1同步的定义「有先后顺序的排他性访问」—— 不仅要保证同一时刻一个资源被一个线程访问还要强制线程按照指定顺序执行如线程 A 执行完后线程 B 才能执行。2与互斥锁的关系互斥包含同步同步是互斥的「特例」互斥只保证排他同步额外保证顺序释放逻辑不同互斥锁加锁 / 解锁是同一个线程信号量线程 A 释放资源线程 B 申请资源交叉释放。3计数信号量的用途信号量初始值可大于 1如 3、5适用于「多份相同资源」的竞争场景如你之前代码中win3的有限资源竞争。2.2 信号量的使用步骤信号量生命周期「定义→初始化→PV 操作→销毁」。1核心函数POSIX 标准操作函数原型关键说明定义sem_t sem;声明信号量变量初始化int sem_init(sem_t *sem, int pshared, unsigned int value);pshared0线程间使用、!0进程间value 初始资源数成功返回 0失败 - 1P 操作申请资源int sem_wait(sem_t *sem);sem0 则 sem-1 并继续sem0 则阻塞成功返回 0失败 - 1V 操作释放资源int sem_post(sem_t *sem);sem1不阻塞成功返回 0失败 - 1销毁int sem_destroy(sem_t *sem);成功返回 0失败 - 12核心规则P 操作sem_wait申请资源资源数 - 1V 操作sem_post释放资源资源数 1信号量临界区可包含短暂休眠 / 耗时操作比互斥锁灵活。3基础示例信号量实现线程同步c运行#include stdio.h #include pthread.h #include semaphore.h #include unistd.h sem_t sem; // 信号量控制线程执行顺序 void* th1(void* arg) { printf(线程1执行初始化操作\n); sleep(2); sem_post(sem); // V操作释放资源sem1 return NULL; } void* th2(void* arg) { sem_wait(sem); // P操作等待资源sem0时阻塞 printf(线程2线程1初始化完成后执行\n); return NULL; } int main() { pthread_t tid1, tid2; sem_init(sem, 0, 0); // 初始化线程间使用初始值0 pthread_create(tid1, NULL, th1, NULL); pthread_create(tid2, NULL, th2, NULL); pthread_join(tid1, NULL); pthread_join(tid2, NULL); sem_destroy(sem); return 0; }三、互斥锁 vs 信号量核心区别维度互斥锁信号量核心目标排他性访问无顺序有序的排他性访问同步释放主体加锁线程自己解锁线程 A 申请线程 B 释放交叉初始值无只有锁定 / 未锁定状态可设为任意非负整数如 0、1、3临界区限制禁止耗时操作必须短小可包含短暂休眠 / 小耗时操作适用场景单一资源的排他访问如全局变量多资源竞争、线程顺序控制四、死锁线程控制的 “致命陷阱”4.1 死锁的定义因锁资源的申请 / 释放逻辑错误导致线程 / 进程永久阻塞无法继续执行的现象。4.2 死锁的四个必要条件缺一不可互斥条件一个资源每次只能被一个线程使用请求与保持条件线程因申请资源阻塞时不释放已持有的资源不剥夺条件线程已获得的资源未使用完前不能被强行剥夺循环等待条件多个线程形成「A 等 B 的资源B 等 C 的资源C 等 A 的资源」的循环。4.3 死锁规避技巧锁的申请顺序一致所有线程按「锁 1→锁 2→锁 3」的顺序申请避免循环等待加锁限时使用pthread_mutex_timedlock替代pthread_mutex_lock超时则放弃避免嵌套锁尽量减少锁的嵌套使用嵌套越多死锁风险越高及时解锁临界区执行完毕立即解锁不持有锁休眠。五、实战场景有限资源的多线程竞争以你之前的「win3 资源竞争」场景为例用信号量替代互斥锁更贴合 “多资源竞争” 的需求c运行#include stdio.h #include pthread.h #include semaphore.h #include unistd.h #include stdlib.h #include time.h int a 0; sem_t sem; // 信号量初始值3代表3个可用资源 void* th_func(void* arg) { while (1) { sem_wait(sem); // P操作申请资源资源数-1 // 临界区可包含短暂休眠 printf(线程%lu获取资源\n, pthread_self()); sleep(rand() % 2); a; printf(线程%lu释放资源a%d\n, pthread_self(), a); sem_post(sem); // V操作释放资源资源数1 if (a 10) break; // 退出条件 } return NULL; } int main() { pthread_t tid[10]; srand((unsigned int)time(NULL)); sem_init(sem, 0, 3); // 初始化线程间使用初始资源数3 for (int i 0; i 10; i) { pthread_create(tid[i], NULL, th_func, NULL); } for (int i 0; i 10; i) { pthread_join(tid[i], NULL); } sem_destroy(sem); printf(最终a的值%d\n, a); return 0; }六、核心总结互斥锁解决「单一资源的排他访问」临界区必须短小加解锁同线程信号量解决「多资源竞争 / 线程同步」支持交叉释放临界区可适度耗时死锁规避打破四个必要条件中的任意一个如统一锁申请顺序即可选型原则单一资源排他访问 → 互斥锁多资源竞争 / 线程顺序控制 → 信号量。