什么是Critical Section Objects?
Critical section object提供了与mutex object(互斥对象)相同的同步机制, 不同之处在于critical section只能被一个进程中的线程使用. Event, mutex和semaphore object也能用在单个进程的应用程序中, 但是critical section objects提供了稍微快一点的, 更有效的互斥同步机制. 如同mutex object, 一个critical section object一次尽可以被一个线程拥有, 这使得他对于并发访问时保护共享资源非常有用. 与mutex object不同的是, 没办法说明一个critical section是否已经被遗弃.
进程负责为critical section使用的内存进行分配. 典型地, 这种分配通过简单地声明一个CRITICAL_SECTION类型的变量来实现. 在进程中的线程可以使用它之前, 需要使用InitializeCriticalSection 或者是InitializeCriticalSectionAndSpinCount函数来初始化critical section.
线程使用EnterCriticalSection 或者是TryEnterCriticalSection函数来请求对critical section的所有权. 它使用LeaveCriticalSection函数来释放对critical section的所有权. 如果critical section对象目前正被另一个线程所拥有, EnterCriticalSection 函数会无限地等待所有权的释放. 相对比, 当一个mutex对象被用在互斥访问中的时候, wait functions会接受一个超时的时间限制. TryEnterCriticalSection 函数会试图进入critical section而不会阻塞调用者线程.
当一个线程拥有critical section的时候, 它能够进行额外的对于EnterCriticalSection 或者TryEnterCriticalSection 的调用, 而不会阻塞它的执行. 这样就阻止了线程在等待它已经拥有了的critical section时把自己死锁掉. 要释放掉它的所有权, 线程必须每次进入critical section时都调用一次LeaveCriticalSection. 哪个等待中的线程会先请求critical section的所有权是不一定的, 没有这种保证.
线程使用InitializeCriticalSectionAndSpinCount 或者SetCriticalSectionSpinCount 函数来制定critical section的spin count. Spin的意思是当一个线程试图获取一个已经被锁掉的critical section的所有权时, 线程会进入一个循环, 去检查这个锁是否已经开启, 如果锁没有被释放, 那么线程就会进入休眠状态. 在单个处理器的系统中, spin count会被忽略掉, 并且critical section spin count会被设置为0. 在多处理器系统中, 如果critical section不可用, 那么调用者线程会在执行与critical section相关的旗语上的等待操作前, 循环dwSpinCount 次. 如果critical section 在spin操作的时候被释放了, 那么调用线程就避免了进入等待的操作.
任何线程都可以使用DeleteCriticalSection函数来释放在critical section对象初始化时分配的系统资源. 这个函数调用结束之后, critical section对象就不能再用来进行同步了.
当一个critical section对象被拥有的时候, 受影响的只是那些在EnterCriticalSection调用中的等待所有权的线程. 没有等待critical section的线程可以自由地继续执行.
代码举例
==========
下面的例子展示了一个线程如何初始化, 进入, 和释放一个critical section. 它使用了InitializeCriticalSectionAndSpinCount, EnterCriticalSection, LeaveCriticalSection, 和 DeleteCriticalSection 函数.
1: // Global variable
2: CRITICAL_SECTION CriticalSection;
3:
4: void main()
5: {
6: ...
7:
8: // Initialize the critical section one time only.
9: if (!InitializeCriticalSectionAndSpinCount(&CriticalSection,
10: 0x80000400) )
11: return;
12: ...
13:
14: // Release resources used by the critical section object.
15: DeleteCriticalSection(&CriticalSection)
16: }
17:
18: DWORD WINAPI ThreadProc( LPVOID lpParameter )
19: {
20: ...
21:
22: // Request ownership of the critical section.
23: EnterCriticalSection(&CriticalSection);
24:
25: // Access the shared resource.
26:
27: // Release ownership of the critical section.
28: LeaveCriticalSection(&CriticalSection);
29:
30: ...
31: }
原文:http://msdn.microsoft.com/en-us/library/ms682530(VS.85).aspx
http://msdn.microsoft.com/en-us/library/ms686908(VS.85).aspx
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律