能力缺口与基础门槛

很多写过几行 C/C++ 代码的人,一旦在 Windows 下碰多线程,代码就变成了薛定谔的猫:单机调试时永远正确,一上高并发压测就随机崩溃或死锁。这门课的下半段专门解决这个痛点。它不教怎么创建线程,而是死磕线程同步。如果你对进程与线程的区别还停留在文字概念,或者没写过基本的 Win32 API 调用,建议先去补上半段的基础。这门课要求你具备 C/C++ 基础语法能力,能看懂指针和句柄操作,并且已经在 Visual Studio 里独立跑过多线程程序。缺什么补什么,如果你面对多个线程同时修改同一个全局变量时,只会加一把粗粒度的大锁然后祈祷不出事,那就是这门课精准定位的受众。

学习顺序与资料练习配合

资料内容的编排有严格的先后依赖,千万别跳跃着看。第一块必须啃等待函数,这是所有同步机制的基石。重点理解单个等待与多个等待在返回值语义上的本质差异,搞清楚超时机制和句柄状态转换的关系。看完这部分,立刻打开你的开发环境,写一个主线程必须等待两个工作线程全部完成才能继续往下走的例子,故意把其中一个线程的执行时间拉长,观察超时返回时的程序状态。第二块是原子操作函数族,这里的重点不是背诵 API,而是建立一种判断力:明白在什么量级的简单数值操作下,原子操作能直接替代重量级锁,以及它在复合操作场景下为什么会失效。建议你自己写一个百万次并发自增的测试用例,分别用加锁和不加锁的原子函数实现,对比 CPU 占用率和执行耗时。第三块是关键段与临界区,这是日常开发中最常用的手段。学习时要特别关注线程在进不去临界区时的状态,理解它和等待函数在用户态与内核态切换上的开销差异。资料包里的示例代码绝对不能只用眼睛看,必须亲手敲一遍并修改并发数量,故意制造死锁场景,再尝试用不同的等待策略去解开它。

学完产出与自测问题

学完这门课,你应该能独立为 Windows 平台下的多线程模块设计同步策略,能准确判断什么场景用原子操作、什么场景必须用临界区,并且具备排查死锁和资源饥饿的基本能力。看完资料后,如果能独立回答以下几个问题,才算真正补齐了这块短板:等待函数返回超时状态和返回失败状态时,你的线程下一步逻辑应该有什么不同的处理?原子操作替换传统加锁,在什么并发量级下收益最大,什么情况下反而引发总线竞争?临界区在发生竞争时,线程处于什么状态,它和内核等待对象的本质区别在哪里?多个线程同时阻塞在同一个临界区上,释放时的唤醒顺序是怎样的,会不会导致某些线程永远拿不到锁?你自己的代码库里,最可能产生死锁的那一行代码在哪,怎么通过日志或调试工具定位到它?能答上来,说明线程同步这块你已经不用靠猜了。

课程目录

1 七日成蝶课程体系说明(2019) (44:54)
2 课程概览,学我所需 (03:09)
3 线程同步-等待函数(一) (24:02)
4 线程同步-等待函数(二) (10:31)
5 线程同步-等待函数(三) (03:09)
6 线程同步-等待函数(四) (04:54)
7 线程同步-等待函数(五) (08:43)
8 线程同步-InterLocked函数(一) (14:44)
9 线程同步-InterLocked函数(二) (08:16)
10 线程同步-InterLocked函数(三) (03:57)
11 线程同步-InterLocked函数(四) (09:13)
12 线程同步-InterLocked函数(五) (05:06)
13 线程同步-InterLocked函数(六) (08:23)
14 线程同步-关键段-临界区(一) (21:40)
15 线程同步-关键段-临界区(二) (12:36)
16 线程同步-关键段-临界区(三) (09:58)
17 线程同步-关键段-临界区扩展 (18:42)
18 线程同步-读写锁SRWLock(一) (07:03)
19 线程同步-读写锁SRWLock(二) (10:00)
20 线程同步-读写锁SRWLock拓展 (05:50)
21 线程同步-事件内核对象(一) (16:21)
22 线程同步-事件内核对象(二) (12:31)
23 线程同步-可等待计时器(一) (19:59)
24 线程同步-可等待计时器(二) (13:39)
25 线程同步-可等待计时器(三) (04:45)
26 线程同步-可等待计时器(四) (08:26)
27 线程同步-信号量Semaphore(一) (07:31)
28 线程同步-信号量Semaphore(二) (09:27)
29 线程同步-互斥量mutex(一) (14:02)
30 线程同步-互斥量mutex(二) (07:01)
31 线程同步-对比与总结 (13:36)
32 线程同步-SignalAndWait (07:58)