Windows 线程同步方式比较

1. 四种同步方式总览

Windows 线程同步的主要方式有四种:

同步方式 所属层级 跨进程支持
关键代码段(Critical Section) 用户模式 ❌ 不支持
互斥对象(Mutex) 内核模式 ✅ 支持
事件对象(Event) 内核模式 ✅ 支持
信号量(Semaphore) 内核模式 ✅ 支持

2. 选型建议

  • 首选关键代码段:使用简单、效率高,适用于同一进程内多线程同步。在 MFC 程序中,可在类的构造函数中调用 InitializeCriticalSection,析构函数中调用 DeleteCriticalSection,在需要保护的代码前后分别调用 EnterCriticalSectionLeaveCriticalSection
  • 需要跨进程同步:使用互斥对象、事件对象或信号量(均为内核对象)。
  • 需要限制并发访问数量:使用信号量(如限制同时访问某资源的线程数)。

3. 详细对比表

比较项 互斥量(Mutex) 事件对象(Event) 信号量(Semaphore) 关键代码段(Critical Section)
是否为内核对象
速度 较慢 较慢 较慢
跨进程同步 ✅ 支持 ✅ 支持 ✅ 支持 ❌ 不支持
死锁风险 较低 较低 较低 ⚠️ 较高(无法设超时)
组成 • 线程 ID(标识拥有者)
• 计数器(递归次数)
• 使用计数
• 重置类型(自动/人工)
• 信号状态(有/无信号)
• 使用计数
• 最大资源数
• 当前可用资源数
一段代码块,访问资源前需获得独占权
核心函数 CreateMutex
WaitForSingleObject
ReleaseMutex
CreateEvent
WaitForSingleObject
SetEvent
ResetEvent
CreateSemaphore
WaitForSingleObject
ReleaseSemaphore
InitializeCriticalSection
EnterCriticalSection
LeaveCriticalSection
DeleteCriticalSection
注意事项 谁拥有谁释放;同一线程多次请求需对应多次 ReleaseMutex 线程同步建议用自动重置bManualReset = FALSE 允许多个线程同时访问,但需限制最大访问线程数 注意防止死锁(尤其使用多个临界区变量时)
形象类比 一把钥匙(谁拿到谁独占) 钥匙(自动重置=一次性钥匙,人工重置=门禁开关) 停车场 + 保安(限制同时进入的车辆数) 电话亭(一次只能一人进入)

4. 关键代码段使用注意事项

注意事项 说明
配对调用 每次 EnterCriticalSection 必须对应一次 LeaveCriticalSection,否则其他等待线程将永远阻塞
死锁风险 使用多个临界区对象时,注意避免循环等待导致的死锁
无超时机制 等待进入关键代码段时无法设定超时值,容易造成线程永久阻塞
不可跨进程 仅限同一进程内的线程使用

5. 什么是线程安全?

线程安全:如果一段代码在多线程环境下执行的结果,与单线程环境下执行的结果完全一致,则该代码是线程安全的