对于CRITICAL_SECTION用法的介绍和理解
来源:互联网 发布:ios 导出沙盒数据 编辑:程序博客网 时间:2024/05/16 09:15
转载来源 http://blog.sina.com.cn/s/blog_7953cead0100osnt.html
很多人对CRITICAL_SECTION的理解是错误的,认为CRITICAL_SECTION是锁定了资源,其实,CRITICAL_SECTION是不能够“锁定”资源的,它能够完成的功能,是同步不同线程的代码段。简单说,当一个线程执行了EnterCritialSection之后,cs里面的信息便被修改,以指明哪一个线程占用了它。而此时,并没有任何资源被“锁定”。不管什么资源,其它线程都还是可以访问的(当然,执行的结果可能是错误的)。只不过,在这个线程尚未执行LeaveCriticalSection之前,其它线程碰到EnterCritialSection语句的话,就会处于等待状态,相当于线程被挂起了。 这种情况下,就起到了保护共享资源的作用。
也正由于CRITICAL_SECTION是这样发挥作用的,所以,必须把每一个线程中访问共享资源的语句都放在EnterCritialSection和LeaveCriticalSection之间。这是初学者很容易忽略的地方。
第一个线程已经执行了EnterCriticalSection(&cs)并且还没有执行LeaveCriticalSection(&cs),这时另一个线程想要执行EnterCriticalSection(&cs2),这种情况是可以的(除非cs2已经被第三个线程抢先占用了)。这也就是多个CRITICAL_SECTION实现同步的思想。
DWORD WINAPI ThreadFuncA(LPVOID lp){ EnterCriticalSection(&cs); ... // 操作dwTime ... LeaveCriticalSection(&cs); return 0;}
如果你像如下的方式来写第二个线程,那么就会有问题:
DWORD WINAPI ThreadFuncB(LPVOID lp){ ... // 操作dwTime ... return 0;}
为了让 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,就以此类推。
再举个极端的例子,可以帮助你理解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其实并不理会你关心的具体共享资源,它只按照自己的规律办事~
- 对于CRITICAL_SECTION用法的介绍和理解
- CRITICAL_SECTION 理解的总结
- 对CRITICAL_SECTION的理解
- CRITICAL_SECTION 理解的总结
- 对CRITICAL_SECTION理解的总结
- 对CRITICAL_SECTION理解的总结
- 对CRITICAL_SECTION理解的总结
- 对CRITICAL_SECTION理解的总结
- 对CRITICAL_SECTION理解的总结
- 对CRITICAL_SECTION理解的总结
- 关于CRITICAL_SECTION的一些理解
- 对CRITICAL_SECTION理解的总结
- 对于EnterCriticalSection和LeaveCriticalSection的理解和用法
- 理解CRITICAL_SECTION
- CRITICAL_SECTION 用法
- CRITICAL_SECTION 理解的总结 EnterCriticalSection LeaveCriticalSection
- CRITICAL_SECTION 理解的总结 EnterCriticalSection LeaveCriticalSection
- 关于CRITICAL_SECTION、CCriticalSection和信号量的问题
- 获取当前正在运行的应用程序的包名以及入口activity
- 编写函数void count(char a[],char w[][10],int n,int b[])。功能是:统计w指向的数组中的n个单词在a指向的字符串中各自出现的次数(将非字母字符看作单词分
- 【高斯消元】bzoj1923千足虫
- 知识管理
- 算法训练 最大最小公倍数
- 对于CRITICAL_SECTION用法的介绍和理解
- 1036. Boys vs Girls (25)
- error和exception的区别,RuntimeException和非RuntimeException的区别
- C共用体
- 浅析PHP类中的静态方法以及静态属性
- 编写函数void count(char a[],char w[][10],int n,int b[])
- iOS常用小功能
- C位运算
- Recorder︱图像语义分割(FCN、CRF、MRF)、论文延伸(Pixel Objectness、)