如果我两次调用EnterCriticalSection和一次LeaveCriticalSection会发生什么? [英] What happens if I call EnterCriticalSection twice and LeaveCriticalSection once

查看:226
本文介绍了如果我两次调用EnterCriticalSection和一次LeaveCriticalSection会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我如下图所示两次调用EnterCriticalSection并一次调用LeaveCriticalSection会发生什么?
执行LeaveCriticalSection后,关键节是否仍会锁定或释放?

EnterCriticalSection
EnterCriticalSection

LeaveCriticalSection


可以请任何一个人澄清吗?
谢谢

What happens if I call EnterCriticalSection twice and LeaveCriticalSection once as shown below?
After executing LeaveCriticalSection, will the critical section still locked or released?

EnterCriticalSection
EnterCriticalSection

LeaveCriticalSection


Can any one please clarify?
Thanks

推荐答案

我认为您的意思是CriticalSection的相同实例.
调用线程没什么问题,但是下一个调用EnterCriticalSection的线程将永远卡在该调用中.

它会被操作系统关闭,并处于等待状态,从不调度执行时间,而花费的CPU时间为零,而且从不唤醒.要唤醒此线程,第一个线程应再次在同一实例上调用LeaveCritical部分,但此调用丢失了.

—SA
I think you mean the same instance of the CriticalSection.
Nothing wrong for the calling thread, but next thread to call EnterCriticalSection will get stuck forever at the call.

It will be switched off by OS and kept in a wait state, never scheduled back for execution spending zero CPU time and never awaken. To wake up this thread the first thread should call LeaveCritical section on the same instance once again, but this call is missing.

—SA


对同一线程没有影响.
(很抱歉,我非常误解了您的问题,我的旧帖子没有任何意义.在同一线程上不会有任何影响...)

建立此代码,它应该消除您的疑虑. (以不同的组合切换进入"和离开".)

There would be no effect on same thread.
(My apology, I misunderstood your question terribly, the my old post doesnt make any sense. There would be no effect on same thread...)

Build this code,it should take away your doubts. (toggle the Enter and Leave in different combinations..)

#include <windows.h>
#include <stdio.h>
CRITICAL_SECTION sectionA;
LONG WINAPI func(LONG);
int wmain(void)
{
	HANDLE hThread;
	DWORD dwordThreadID;
	long i = 50;
	printf("The current thread ID is %u\n", GetCurrentThreadId());
	InitializeCriticalSection(&sectionA);
	hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)func,NULL,0,&dwordThreadID);
	CloseHandle(hThread);
	while(i--)
	{    
		EnterCriticalSection(&sectionA);
		printf("Main Thread Entered : Locked Section A for (%u) \n", GetCurrentThreadId());
		EnterCriticalSection(&sectionA);
		printf("Again Thread Entered : Locked Section A for (%u) \n", GetCurrentThreadId());
		LeaveCriticalSection(&sectionA);        
		printf("Main Thread releasing  (%u) critical sections\n", GetCurrentThreadId());
		// Remove this section and see 
		// LeaveCriticalSection(&sectionA);        
		Sleep(200);
	};
	return 0;
}
LONG WINAPI func(LONG lParam)
{
	long l=50;
	while(l--)
	{
		printf("Thread Trying to access \n", GetCurrentThreadId());
		EnterCriticalSection(&sectionA);
		printf("Thread2 Entered : Locked Section A for (%u) \n", GetCurrentThreadId());
		EnterCriticalSection(&sectionA);
		printf("Thread2 Entered : Locked Section A for (%u) \n", GetCurrentThreadId());
		LeaveCriticalSection(&sectionA);
		// Remove this section and see
		// LeaveCriticalSection(&sectionA);
		printf("Thread2 releasing (%u) critical sections\n", GetCurrentThreadId());
		Sleep(200);
	};
}



希望这对您有帮助...



Hope this helps...


CS锁定由锁定计数管理.如果您两次输入它并退出其中一个,则您仍然拥有一个锁,因此没有 other 线程可以锁定CCS(它们都将等待您的线程释放所有锁,即:您所有必须先释放"入口",然后其他人才能进入".

但请注意,就像
CS locking is managed by a lock count. If you enter it twice and exit one, you have still one lock owned, and hence no other thread can lock the CCS (they all will wait for your thread to release all locks, that is: all your "entrance" must be "leaved" before someone else can "enter").

But note that, in loop, like
for(.,.,.)
{
   EnterCriticalSection(.);
   EnterCriticalSection(.);
   LeaveCriticalSection(.);
}


只有一个线程:因此它将很好地运行循环.每次迭代将添加2个删除对象.
Wen确实存在,您还有许多待处理的锁.

在其他情况下,例如


there is just one thread: so it will run the loop nicely. It will add 2 remove one for each iteration.
Wen it exists, you''re left with a number of lock pending.

In anoter case like

EnterCriticalSection(.);
for(.,.,.)
{
    EnterCriticalSection(.);
    LeaveCriticalSection(.);
}
LeaveCriticalSection(.)


一切都很好.当然,内部Enter/Leave在这种情况下没有实际作用,但是它们可以保留在可以在循环内或循环外调用的函数体内.

通常,一个好的做法是将相等数量的Enter/Leave放入相同的作用域({}对),或者让它们由堆栈上的变量构造/销毁管理,例如


everithing is fine. Of course, the inner Enter/Leave in this case have no practical effect, but they can stay inside a function body that can be called either inside or outside the loop.

In general a good practice is to place an equal number of Enter/Leave into a same scope ( {} pairs) or let them be managed by a on-stack variable contruction / destruction, like

/// RAII enter/leave
class ccs_locker
{
   CRITICAL_SECTION* pcs;
public:
   ccs_locker(CRRITICAL_SECTION& cs) :pcs(&cs) { EnterCriticalSection(pcs); }
   ~ccs_unlocker() { LeaveCriticaSection(pcs); }
private:
   /// disable copy and assign
   ccs_locker(const ccs_locker&);
   ccs_locker& operator=(const ccs_locker&);
};


/// CRITSEC initializer
class criticalsection: public CRITICAL_SECTION
{
public:
   criticalsection() { InitializeCriticalSection(this); }
   ~criticalsection() { DeleteCriticalSection(this); }
private:
   //disable copy and assign
   criticalsection(const criticalsection&);
   criticalsection& operator=(const criticalsection&);
};

///now a proper always good code
{
  criticalsection cs;
    ccs_locker lock1(cs);
    for(...)
    {
      ccs_locker lock2(cs);
      ...
      if(...) return;
      ...
      if(...) throw ...;
      ...
      if(...) break;
      ...
    }
return;
}



道德:无论您如何返回,抛出或中断:析构函数都会始终调整调用对.



Moral: no matter how you return, throw or break: destructor will always adjust the call pairs.


这篇关于如果我两次调用EnterCriticalSection和一次LeaveCriticalSection会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆