用户模式同步
Interlocked 系列函数
- 原理
- 通过
CPU
原子指令(如LOCK XCHG
)直接操作内存,无需进入内核态
- 通过
- 场景
- 简单计数器(如引用计数)
- 无锁数据结构(如无锁队列)
- 特点
- 性能极高(无内核切换)
- 仅支持单个变量的原子操作,无法实现复杂同步
1 2 3 4 |
LONG __cdecl InterlockedIncrement(LONG volatile* Addend); // 原子加1 LONG __cdecl InterlockedDecrement(LONG volatile* Addend); // 原子减1 LONG __cdecl InterlockedExchange(LONG volatile* Target, LONG Value); // 原子赋值 LONG __cdecl InterlockedCompareExchange(LONG volatile* Dest, LONG Exch, LONG Comp); // CAS操作 |
临界区(Critical Section)
- 原理
- 进程内轻量级互斥锁,通过自旋(
Spin
)减少内核切换
- 进程内轻量级互斥锁,通过自旋(
- 场景
- 同一进程内多线程对共享资源的互斥访问
- 高频、短时间持有的锁
- 限制
- 不能跨进程使用
- 不支持超时等待
API
1 2 3 4 5 |
CRITICAL_SECTION cs; InitializeCriticalSection(&cs); // 初始化 EnterCriticalSection(&cs); // 加锁(可能自旋等待) LeaveCriticalSection(&cs); // 解锁 DeleteCriticalSection(&cs); // 销毁 |
- 高级选项
1 2 |
// 初始化时设置自旋次数(减少内核切换) InitializeCriticalSectionAndSpinCount(&cs, 4000); |
内核对象同步(Kernel-Mode Synchronization)
信号量(Semaphore)
- 原理
- 内核对象,维护一个计数器,控制同时访问资源的线程数
- 场景
- 限制资源并发访问数(如数据库连接池)
- 跨进程资源池管理
- 特点
- 计数器范围:
0
到创建时指定的最大值
- 计数器范围:
API
1 2 3 |
HANDLE hSemaphore = CreateSemaphore(NULL, 5, 5, L"Global\\MySemaphore"); // 初始值=5,最大值=5 WaitForSingleObject(hSemaphore, INFINITE); // 减少计数器(若为0则阻塞) ReleaseSemaphore(hSemaphore, 1, NULL); // 增加计数器(+1) |
互斥量(Mutex)
- 原理
- 内核对象,支持跨进程互斥访问,所有权机制(仅持有者能释放)
- 场景
- 跨进程资源保护(如共享内存、文件)
- 需要严格所有权的场景
- 特点
- 可跨进程:通过命名互斥量(如
Global\\
前缀)实现 - 递归获取:同一线程可多次加锁(需对应次数释放)
- 可跨进程:通过命名互斥量(如
API
1 2 3 4 |
HANDLE hMutex = CreateMutex(NULL, FALSE, L"Global\\MyMutex"); // 创建/打开命名互斥量 WaitForSingleObject(hMutex, INFINITE); // 等待锁 ReleaseMutex(hMutex); // 释放锁 CloseHandle(hMutex); // 关闭句柄 |
事件(Event)
- 原理
- 内核对象,用于线程间通知(手动重置/自动重置)
- 场景
- 线程间单向通知(如生产者-消费者模型)
- 复杂同步逻辑(如多条件等待)
- 对比
- 手动重置:广播唤醒所有等待线程
- 自动重置:每次触发仅唤醒一个线程
API
1 2 3 4 5 6 7 |
// 创建事件(手动重置:需显式ResetEvent) HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, L"MyEvent"); SetEvent(hEvent); // 触发事件(所有等待线程被唤醒) ResetEvent(hEvent); // 手动重置为未触发状态 // 自动重置事件(触发后仅唤醒一个线程) HANDLE hAutoEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
可等待计时器(Waitable Timer)
- 原理
- 内核对象,用于线程在指定时间或周期被唤醒
API
1 2 3 4 5 |
HANDLE hTimer = CreateWaitableTimer(NULL, TRUE, L"MyTimer"); LARGE_INTEGER liDueTime; liDueTime.QuadPart = -10000000; // 1秒后触发(负值表示相对时间) SetWaitableTimer(hTimer, &liDueTime, 1000, NULL, NULL, FALSE); // 周期1秒 WaitForSingleObject(hTimer, INFINITE); // 等待触发 |
读写锁(Slim Reader-Writer Lock)
- 原理
- 允许多个读线程或单个写线程访问资源,优化读多写少场景
- 优点
- 用户模式实现,性能接近临界区
- 无递归支持,需避免重复加锁
- 场景
- 高频读取、低频写入的数据结构(如配置缓存)
API
1 2 3 4 5 6 7 8 9 10 |
SRWLOCK srwLock; InitializeSRWLock(&srwLock); // 读模式加锁(共享) AcquireSRWLockShared(&srwLock); ReleaseSRWLockShared(&srwLock); // 写模式加锁(独占) AcquireSRWLockExclusive(&srwLock); ReleaseSRWLockExclusive(&srwLock); |
条件变量(Condition Variable)
- 原理
- 与临界区或读写锁配合,实现线程等待特定条件成立
- 场景
- 生产者-消费者模型(当队列空/满时阻塞)
- 复杂状态依赖的同步逻辑
API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
CONDITION_VARIABLE cv; InitializeConditionVariable(&cv); // 等待条件(需配合临界区) CRITICAL_SECTION cs; EnterCriticalSection(&cs); while (condition_not_met) { SleepConditionVariableCS(&cv, &cs, INFINITE); } LeaveCriticalSection(&cs); // 触发条件 WakeConditionVariable(&cv); // 唤醒一个等待线程 WakeAllConditionVariable(&cv); // 唤醒所有等待线程 |
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Windows 核心编程 _ 内核对象二06/07
- ♥ Windbg:命令实践详解二03/28
- ♥ C++_多线程相关03/12
- ♥ 线程和协程10/31
- ♥ 包管理器:设计与实现09/18
- ♥ C++并发编程 _ 共享数据05/16