关于TryEnterCriticalSection函数的问题!C/C++ codebool flagCRITICAL_SECTION g_csUINT _stdcall Func1
关于TryEnterCriticalSection函数的问题!
C/C++ codebool flag;CRITICAL_SECTION g_cs;UINT _stdcall Func1( void *dummy ){ printf("Func1\n"); if (TryEnterCriticalSection(&g_cs) == FALSE) printf("Try Failed!!!\n"); if (flag == true) printf("TRUE NOW!\n"); else printf("FALSE NOW!\n"); LeaveCriticalSection(&g_cs); return 0;}UINT _stdcall Func2( void *dummy ){ printf("Func2\n"); EnterCriticalSection(&g_cs); Sleep(5000); LeaveCriticalSection(&g_cs); return 0;}void main(){ unsigned long Thread1 = 0, Thread2 = 0; UINT Func1Code = 0, Func2Code = 0; flag = false; InitializeCriticalSection(&g_cs); Thread2 = _beginthreadex(NULL, 0, Func2, NULL, 0, &Func2Code); Sleep(1000); Thread1 = _beginthreadex(NULL, 0, Func1, NULL, 0, &Func1Code); system("pause"); DeleteCriticalSection(&g_cs);}
这是我写的一个测试线程同步的代码,《windows核心编程里》说,TryEnterCriticalSection()函数可以替代EnterCriticalSection()这个函数,两者的区别,MSDN上说,TryEnterCriticalSection()是不阻塞的,而EnterCriticalSection()是阻塞的。
照我的理解,TryEnterCriticalSection()函数如果返回FALSE的话,那么临界区是进不去的。但事实却相反,TryEnterCriticalSection()返回FALSE,临界区还是进去了。
郁闷...请赐教!
[解决办法]up
[解决办法]以上代码并不足以对“TryEnterCriticalSection()函数如果返回FALSE的话,那么临界区是进不去的。但事实却相反,TryEnterCriticalSection()返回FALSE,临界区还是进去了”做出判断。
[解决办法]事实正因为TryEnterCriticalSection不阻塞,fun1得以继续执行.
另外LeaveCriticalSection 必须只在TryEnterCriticalSection成功的时候调用。
[解决办法]可以这样(参考一下):
if (TryEnterCriticalSection(&gCriticalSection))
{
try
{
//Do something here
}
__finally
{
LeaveCriticalSection(&gCriticalSection);
}
}
TryEnterCriticalSection如果执行没有成功,就表示没有锁定临界区,所以不需要使用LeaveCriticalSection,只有当成功的时候对需要使用LeaveCritialSection.
TryEnterCriticalSection和EnterCriticalSection不同点在于前者是无论成功还是失败都立即返回,如果失败则返回0,否则返回非零值,调用成功,则必须使用LeaveCriticalSection配对释放锁定,否则其它线程将会在本线程关闭或者gCriticalSection被销毁前无法对相关的共享资源进行访问;后者则是一直等待,真到成功锁定资源,因为后者不论如何也都需要有LeaveCriticalSection配对。
要注意的是EnterCriticalSection返回值是一个void,意思也就是它是“只许成功不许失败”,但是却也有偶然失败的时候,这是MS$当初所料不及的,因为把返回值设成了void.
默认尝试锁定等待时长大约为30天(由注册表键值CriticalSectionTimeout, HKEY_LOCAL_MACHINE\SYSTEM\CURRENTCONTROLSET\CONTROL\SESSION MANGER ,单位为秒).如果EnterCriticalSection调用失败将会得到一个异常,此时最好使用调试器进行调试,以确定问题所在。
[解决办法]up
[解决办法]TryEnterCriticalSection()既然不阻塞,当然可以继续执行了,要阻塞的话,还是用EnterCriticalSection()