新闻详情

新闻详情

首页 / 资讯中心 / 详情

第 5 天:锁住的到底是什么?

发布时间:2026/10/2 2:28:48来源:尧图网络
第 5 天:锁住的到底是什么?
昨天两条线程各做了十万次“加一”结果却可能不到二十万。问题出在这里读取旧值、计算、写回必须作为一个整体完成另一条线程不能插进来。最直接的办法是给这段操作加一把锁pthread_mutex_lock(mutex);counter;pthread_mutex_unlock(mutex);两条线程必须使用同一把锁。一条线程拿到锁后另一条要等它释放才能进入这段代码。这种同一时刻只允许一个线程进入的区域叫临界区。锁并不是贴在counter上的封条。它保护的是程序员约定好的一段操作所有访问这份共享数据的线程都得遵守同一约定。只要有一处绕开锁保护就可能失效。不过线程有时需要的不只是“别同时动数据”。它还需要等一句话变成真货架上有东西才能取货架空了才能放。一格货架两个线程我们做一个只有一格的缓冲区主线程负责生产数字1到5一次放一个。工作线程负责取走数字。slot存数字full表示这一格是否已被占用。这里要保护的其实是一条规则full 1时slot里必须有一个可取的数字。修改slot和full的过程不能被另一条线程看到一半。把下面代码保存为queue.c在 Linux 或 WSL 中运行#includepthread.h#includestdio.h#includestring.h#includeunistd.henum{COUNT5};staticintslot;staticintfull0;staticpthread_mutex_tmutexPTHREAD_MUTEX_INITIALIZER;staticpthread_cond_tnot_emptyPTHREAD_COND_INITIALIZER;staticpthread_cond_tnot_fullPTHREAD_COND_INITIALIZER;staticvoid*consume(void*arg){(void)arg;for(inti0;iCOUNT;i){pthread_mutex_lock(mutex);while(!full){pthread_cond_wait(not_empty,mutex);}intitemslot;full0;pthread_cond_signal(not_full);pthread_mutex_unlock(mutex);printf(取走 %d\n,item);sleep(1);}returnNULL;}intmain(void){pthread_tconsumer;interrorpthread_create(consumer,NULL,consume,NULL);if(error!0){fprintf(stderr,创建线程失败%s\n,strerror(error));return1;}for(inti1;iCOUNT;i){pthread_mutex_lock(mutex);while(full){pthread_cond_wait(not_full,mutex);}sloti;full1;printf(放入 %d\n,i);pthread_cond_signal(not_empty);pthread_mutex_unlock(mutex);}pthread_join(consumer,NULL);return0;}编译运行gcc-stdc11-Wall-Wextra-pthread-oqueue queue.c ./queue你会看到数字依次被放入、取走。消费者每取一个都会暂停一秒因此生产者很容易遇到“货架已满”必须等消费者腾出位置。程序并不要求两个线程按某个固定时间交替运行不管谁先拿到 CPU都不能覆盖未取走的数字也不能从空货架取东西。等待时为什么要把锁放开看生产者的这几行pthread_mutex_lock(mutex);while(full){pthread_cond_wait(not_full,mutex);}如果货架满了生产者不能一直拿着锁等待。消费者也需要这把锁才能取走数字、把full改成0。生产者不放锁消费者进不来消费者进不来货架就永远不会空。pthread_cond_wait帮我们完成关键动作放开锁并进入等待被唤醒后重新拿到锁再从函数返回。“放锁并等待”作为一个配套动作完成避免线程刚放开锁、还没开始等待时错过另一条线程发出的通知。消费者取走数字后调用pthread_cond_signal(not_full)告诉等待“货架有空位”的线程你可以起来再检查了。生产者放入数字时也用not_empty通知消费者。注意“通知了”不等于“条件现在一定成立”。线程被唤醒、重新拿到锁之前其他线程可能已改变状态等待也可能无缘无故结束。因此代码用的是while不是ifwhile(full){pthread_cond_wait(not_full,mutex);}醒来后再检查full。真空了才继续放仍然满就接着等。**条件变量负责通知full才是判断能否继续的依据。**如果发通知时没人等待条件变量不会替你“存下一次通知”共享状态仍要由程序自己记录。为什么不用一个循环反复检查可以写出这样的代码while(full){/* 一直检查 */}它看似也在等待实际上可能持续消耗 CPU。如果还拿着互斥锁循环消费者根本无法把full改掉即使不拿锁也得正确处理共享数据的同步问题。条件变量让线程在条件不满足时睡眠等状态改变再来检查。这和第 3 天讲的调度接上了等货架空位的线程此刻不需要 CPU 来做计算。信号量又解决什么问题生产者—消费者问题也常用信号量来写。信号量内部维护一个计数wait尝试把计数减一没额度就等待post把计数加一并可能唤醒等待者。对一格货架可以设空位数 empty 1 物品数 items 0 生产者等待 empty → 放入物品 → 增加 items 消费者等待 items → 取走物品 → 增加 empty互斥锁、条件变量和信号量的侧重点不同工具在这里解决的问题互斥锁修改货架状态时别让另一条线程同时修改条件变量货架满或空时睡眠并等待状态变化信号量记录可用空位或物品的数量如果扩展到多个生产者、多个消费者只靠表示数量的信号量还得仔细保护实际读写货架的过程。这篇代码里最值得记住的是两条线**改共享状态时拿锁条件不满足时放锁等待醒来再检查。**下一篇要看如果两个线程各拿着一把锁偏偏又等对方放锁会发生什么。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

tlb mm_needs_global_asid 2026/10/2 13:53:15

tlb mm_needs_global_asid

mm_needs_global_asid 是 x86 架构中用于判断一个进程是否正在从本地 ASID 过渡到全局 ASID 的辅助函数。代码定义根据搜索结果,其实现如下:static bool mm_needs_global_asid(struct mm_struct *mm, u16 asid) {u16 global_asid mm_global_asid(mm);if…

阅读更多 →
【第2 章】WorkBuddy 从入门到高手 2026/10/2 13:53:15

【第2 章】WorkBuddy 从入门到高手

WorkBuddy 从入门到高手(第 2章):核心能力,办公六件套全拆解(超详细案例版) 这是一套面向「完全没用过 WorkBuddy」读者的系统学习路线,总共 7 章。本文是第 3 章。 系列目录:第 0 章…

阅读更多 →
面试白板必考!手撕快排:三种partition写法 + 七个致命坑 + 一套默写模板 2026/10/2 13:53:15

面试白板必考!手撕快排:三种partition写法 + 七个致命坑 + 一套默写模板

面试里有个残酷的事实:快排你“懂”和你能“写出来”是两件事。 懂的人能跟你聊半天复杂度,真到白板前,往往卡在三个地方: 哨兵指针的初始位置差一位内外层循环要不要加等号递归边界是p-1还是p 这三处任意一个写错,10分…

阅读更多 →
tlb consider_global_asid 2026/10/2 13:53:14

tlb consider_global_asid

consider_global_asid 是 x86 架构中一个周期性触发的检查函数,用于判断当前进程是否“值得”分配全局 ASID。它并不直接执行分配,而是通过采样机制和阈值判断,决定是否调用 use_global_asid 来真正分配。核心逻辑:采样 阈值 分…

阅读更多 →
tlb finish_asid_transition 2026/10/2 13:53:13

tlb finish_asid_transition

finish_asid_transition 是 AMD 广播 TLB 失效(Broadcast TLB Invalidation)补丁集中的关键同步函数。它的核心任务是:在完成一次广播 TLB 刷新后,确认所有正在运行该进程的 CPU 都已经切换到了新的全局 ASID,然后清除…

阅读更多 →
幽门螺杆菌根除,有望“少吃两种药“?双联方案 2026 专家共识来了 2026/10/2 13:52:55

幽门螺杆菌根除,有望“少吃两种药“?双联方案 2026 专家共识来了

幽门螺杆菌根除,有望"少吃两种药"?双联方案 2026 专家共识来了 InfoXMed是面向医生、医学生和医学科研人员的AI医学工具平台,提供文献检索、全文翻译、AI解读、指南查询和题库练习等功能,辅助临床学习、科研汇报与医学备…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉