比如说我们定义了一个共享资源dwTime[100],两个线程ThreadFuncA和ThreadFuncB都对它进行读写操作。当我们想要保证dwTime[100]的操作完整性,即不希望写到一半的数据被另一个线程读取,那么用CRITICAL_SECTION来进行线程同步如下:
第一个线程函数:
DWORD WINAPI ThreadFuncA(LPVOID lp)
{
EnterCriticalSection(&cs);
...
// 操作dwTime
...
LeaveCriticalSection(&cs);
return 0;
}
写出这个函数之后,很多初学者都会错误地以为,此时cs对dwTime进行了锁定操作,dwTime处于cs的保护之中。一个“自然而然”的想法就是——cs和dwTime一一对应上了。
这么想,就大错特错了。dwTime并没有和任何东西对应,它仍然是任何其它线程都可以访问的。如果你像如下的方式来写第二个线程,那么就会有问题:
DWORD WINAPI ThreadFuncB(LPVOID lp)
{
...
// 操作dwTime
...
return 0;
}
当线程ThreadFuncA执行了EnterCriticalSection(&cs),并开始操作dwTime[100]的时候,线程ThreadFuncB可能随时醒过来,也开始操作dwTime[100],这样,dwTime[100]中的数据就被破坏了。
为了让CRITICAL_SECTION发挥作用,我们必须在访问dwTime的任何一个地方都加上EnterCriticalSection(&cs)和LeaveCriticalSection(&cs)语句。所以,必须按照下面的方式来写第二个线程函数:
DWORD WINAPI ThreadFuncB(LPVOID lp)
{
EnterCriticalSection(&cs);
...
// 操作dwTime
...
LeaveCriticalSection(&cs);
return 0;
}
这样,当线程ThreadFuncB醒过来时,它遇到的第一个语句是EnterCriticalSection(&cs),这个语句将对cs变量进行访问。如果这个时候第一个线程仍然在操作dwTime[100],cs变量中包含的值将告诉第二个线程,已有其它线程占用了cs。因此,第二个线程的EnterCriticalSection(&cs)语句将不会返回,而处于挂起等待状态。直到第一个线程执行了LeaveCriticalSection(&cs),第二个线程的EnterCriticalSection(&cs)语句才会返回,并且继续执行下面的操作。
这个过程实际上是通过限制有且只有一个函数进入CriticalSection变量来实现代码段同步的。简单地说,对于同一个CRITICAL_SECTION,当一个线程执行了EnterCriticalSection而没有执行LeaveCriticalSection的时候,其它任何一个线程都无法完全执行EnterCriticalSection而不得不处于等待状态。
再次强调一次,没有任何资源被“锁定”,CRITICAL_SECTION这个东东不是针对于资源的,而是针对于不同线程间的代码段的!我们能够用它来进行所谓资源的“锁定”,其实是因为我们在任何访问共享资源的地方都加入了EnterCriticalSection和LeaveCriticalSection语句,使得同一时间只能够有一个线程的代码段访问到该共享资源而已(其它想访问该资源的代码段不得不等待)。
这就是使用一个CRITICAL_SECTION时的情况。你应该要知道,它并没有什么可以同步的资源的“集合”。这个概念不正确。
如果是两个CRITICAL_SECTION,就以此类推。
修改 删除 举报 引用 回复
加为好友
发送私信
在线聊天
woodcheaper
等级:
可用分等级:长工
总技术分:160
总技术分排名:68278
发表于:2007-07-17 22:51:389楼 得分:15
再举个极端的例子,可以帮助你理解CRITICAL_SECTION这个东东:
第一个线程函数:
DWORD WINAPI ThreadFuncA(LPVOID lp)
{
EnterCriticalSection(&cs);
for(int i=0;i <1000;i++)
Sleep(1000);
LeaveCriticalSection(&cs);
return 0;
}
第二个线程函数:
DWORD WINAPI ThreadFuncB(LPVOID lp)
{
EnterCriticalSection(&cs);
index=2;
LeaveCriticalSection(&cs);
return 0;
}
这种情况下,第一个线程中间总共Sleep了1000秒钟!它显然没有对任何资源进行什么“有意识”的保护;而第二个线程是要访问资源index的,但是由于第一个线程占用了cs,一直没有Leave,而导致第二个线程不得不登上1000秒钟……
第二个线程,真是可怜哪。。。
这个应该很说明问题了,你会看到第二个线程在1000秒钟之后开始执行index=2这个语句。
也就是说,CRITICAL_SECTION其实并不理会你关心的具体共享资源,它只按照自己的规律办事~
发表评论
-
字节对齐
2009-09-11 15:27 764本文主要包括二个部分 ... -
到底什么时候用指针
2009-06-08 10:33 2318在c/c++编程中,到底什么时候该用指针来传递参数呢?总结如下 ... -
IP组播的地址映射分析
2008-11-22 12:58 3740IP组播地址,23对于MAC23位,是怎么换算的? ... -
http://www.java3z.com/cwbwebhome/article/article2a
2008-10-31 21:13 8981.位图的理解 我们都明白图形格式中位图储存方式,其 ... -
http://blog.csdn.net/qw_study/arc
2008-10-31 21:03 1073基本思想: 定义一个带排序数中的最大数为DataForSto ... -
字符常量区
2008-10-23 20:26 1369最近写C常常遇到STATUS_ACCESS_VIOLATION ... -
线程函数
2008-10-23 19:40 820在c++中写多线程程序时候,经常出现: error C2 ... -
c++线程
2008-10-23 19:37 1771C/C++ Runtime 多线程函数 一 简单实例(来自c ... -
http://fevair.itpub.net/post/23540/212646
2008-09-27 21:26 888程序员对于Windows程序中 ... -
位图算法-找中值
2008-09-22 19:25 1898// // Sample for vector arithme ... -
学习札记:使用const 提高函数的健壮性
2008-09-19 11:37 85411.1 使用const 提高函数的健壮性 看到const 关 ... -
深入理解sizeof
2008-09-18 09:30 806最近在论坛里总有人问关于sizeof的问题,并且本人对这个问题 ...
相关推荐
临界区(Critical Region)是多线程编程中一个至关重要的概念,用于解决并发执行时可能出现的数据竞争问题。在多线程环境下,当多个线程同时访问共享资源时,如果没有适当的同步机制,可能会导致数据不一致或者错误...
综上所述,临界区管理是操作系统中一个非常重要的概念,涉及到多进程和多线程环境下的资源共享问题。正确地管理和保护临界区不仅可以提高系统的稳定性和安全性,还能优化程序的性能。通过学习上述各种方法,开发者...
而`sequence`可能是一个示例程序或者分析了线程进入和退出临界区的顺序。 总的来说,理解和有效解决临界区互斥问题对于编写可扩展和可靠的并发程序至关重要。开发者需要根据具体的应用场景和系统特性选择合适的同步...
为了解决这些问题,程序员可以使用线程临界区来确保在同一时刻只有一个线程可以访问特定的代码段或数据。 在"CriticalSection.rar"这个压缩包中,包含了几个关键文件,它们一起构成了一个简单的示例程序,演示了...
"临界区"和"多线程同步"是解决这一问题的关键概念。临界区是一种同步机制,它允许一次只有一个线程访问特定的代码区域或资源,以避免并发访问时可能产生的数据竞争和不一致性。多线程同步则是为了协调多个线程的执行...
- **临界区**:代码中访问共享资源的部分被称为临界区,必须实现互斥访问。 在本例中,通过使用`WaitForSingleObject`和`ReleaseMutex`函数来实现对缓冲区的互斥访问。 **3. 使用信号量管理缓冲区状态** - **信号...
通过阅读和分析提供的源代码,你可以深入理解临界区的工作原理,以及如何在实际项目中应用。记住,合理地使用临界区和其他同步机制可以有效地避免数据竞争,提高多线程程序的稳定性和性能。在这个例子中,你可能会...
"VC多线程例程七及图解文档(使用临界区机制进行线程同步)"提供了关于如何在Visual C++中实现线程同步的实例和详细解释。 1. **多线程基础**:多线程是指一个进程中可以同时存在多个执行流程,每个流程称为一个线程...
总的来说,临界区的互斥控制是多线程编程中解决资源竞争问题的关键技术。MATLAB虽然主要用于科学计算和数据分析,但其支持C/C++编程,因此也可以利用上述的互斥控制手段来实现多线程的同步和通信。理解和熟练运用...
综上所述,该教案深入探讨了软件层面实现进程互斥进入临界区的各种策略,通过不同算法的优缺点分析,帮助学生理解和掌握多进程环境下的资源访问控制机制。同时,还提及了硬件支持下的解决方案,强调了在实际系统中...
标题中的“行业分类-设备装置-一种用于在多核平台下优化关键临界区的方法”表明,这个压缩包内含的资源是关于多核处理器环境下,优化关键代码区域的策略和技术。关键临界区(Critical Section)是多线程编程中的一个...
### Delphi多线程编程:使用临界...正确地使用临界区可以帮助开发者避免多线程环境下的竞态条件问题,确保程序的稳定性和可靠性。在实际开发中,还需要根据具体的应用场景灵活调整临界区的使用策略,以达到最佳的效果。
山洪灾害临界雨量分析是预防和减轻山洪灾害的关键技术之一,它涉及到对降雨量与山洪灾害之间关系的深入理解。全国山洪灾害防治规划中的这一细则旨在为各地提供一个统一的标准和方法,以更准确地评估潜在的灾害风险。...
为了解决这个问题,可以使用锁(如C#的`synchronized`关键字或`lock`语句)或者`Monitor`类实现临界区保护,确保同一时刻只有一个线程可以写入日志。 3. **临界区保护**: - 临界区是一种同步机制,用于控制对共享...
Dekker算法确实可以解决同步互斥问题,因为它通过共享变量确保了不会发生两个进程同时进入临界区的情况。每个进程在进入临界区之前都会检查其他进程的状态,并根据`turn`变量的值决定是否等待。由于没有硬件支持,这...
通过合理运用临界区、互斥对象、信号量等同步机制,可以有效地解决多线程环境下的资源共享问题,提高程序的稳定性和安全性。此外,还需要注意异常处理以及线程局部存储的应用,进一步提升多线程程序的质量。
本文所讨论的“重力坝应力的临界能量误差限自适应有限元分析”,涉及到了当前坝体设计中计算精度和效率之间的平衡问题,尤其是在采用有限元法进行应力分析时。 有限元法(FEM)是一种数值计算方法,广泛用于工程...
临界区(CriticalSection)是...通过学习和分析这个示例项目,开发者可以深入理解临界区的工作原理,掌握在Windows环境下如何使用临界区API来实现线程同步,并在实际项目中应用这些知识来解决多线程编程中的问题。