《Windows核心编程系列》谈谈用户模式下的线程同步

发表于:2012-10-17 09:55

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:ithzhang    来源:51Testing软件测试网采编

  要使用关键段首先需要定义CRITICAL_SECTION结构。然后把任何需要共享的代码放在EnterCriticalSection和LeaveCriticalSection之间。

  如

Int g_a=0;
CRITICAL_SECTION cs;
DWORD WINAPI ThreadProc1(PVOID)
{
EnterCriticalSection(&g_a);
for(int i=0;i<100;i++)
  g_a++;
LeaveCriticalSection(&cs);
 return 0;
}
DWORD WINAPI ThreadProc2(PVOID)
{
EnterCriticalSection(&g_a);
 for(int i=0;i<100;i++)
  g_a++;
LeaveCriticalSection(&cs);
return 0;
}

  作者使用了一个非常形象的比喻。CRITICAL_SECTION结构就像一个卫生间,卫生间内的区域就是要保护的资源。在同一时刻只允许一个人进入卫生间内。如果有多个区域需要保护可以分别定义多个CRITICAL_SECTION结构。调用EnterCriticalSection传入CRITICAL_SECTION结构的地址,这个结构标识要访问的保护资源,也就相当于卫生间。当一个人想上卫生间时,必须首先检查卫生间门上的占用标识,看是否有人占用。如果此时无人,那么EnterCriticalSection将允许调用线程进入卫生间。如果卫生间已有人占用,那么调用线程必须在门外等待。如果一个人使用过卫生间后,他必须把卫生间改为未占用状态。LeaveCriticalSection告诉系统它已经离开了所占用的资源。如果忘记调用LeaveCriticalSection,系统会一直让等待进入此卫生间的人在门外等待。

  关键段由于在内部使用了Interlock系列函数因此执行速度非常快。它的缺点是不能在多进程之间对线程进行同步。而信号量和事件则可以。

  一般情况下CRITICAL_SECTION结构会作为全局变量来分配,这样进程内的所有线程都可以通过该变量来访问这些结构。实际使用中将此结构作为局部变量、从堆中分配或者是类的私有成员也都是可以的。

  但有两个必要条件:

  第 一:想要访问资源的线程必须知道用来访问资源的CRITICAL_SECTION结构的地址。

  第二:在任何线程访问被保护的资源之前,必须对CRITICAL_SECTION结构进行初始化。初始化调用:

VOID InitializeCriticalSection(PCRITICAL_SECTION pcs);

  此函数会设置CRITICAL_SECTION结构的一些成员。如果这些成员没有经过初始化,结果将是不可预料的。

  当线程不需要访问共享资源时,应该调用以下函数来清理CRITICAL_SECTION结构:

   <SPAN style="FONT-SIZE: 18px">VOID DeleteCriticalSection(PCRITICAL_SECTION pcs);</SPAN>

  在访问共享资源调用EnterCriticalSection,该函数将执行下面的动作:

  1:如果没有线程在访问资源,该函数会更新成员变量,表示线程已经获得对资源的访问权,同时更新调用线程被准许访问的次数。线程可以继续执行。

  2:如果有其他线程占用资源,该函数会使用一个事件内核对象把调用线程切换到等待状态。当占用线程调用LeaveCriticalSection时,系统会自动更新CRITICAL_SECTION的成员变量并将挂起的线程切换到可调度状态。

  为了防止当资源被其他线程占用时,主调线程被挂起,可以调用TryEnterCriticalSection函数,该函数将会检测此时主调线程是否可以访问共享资源。如果资源被占用该函数返回false。否则返回true。

  如果检测到资源此时已被占用,主调线程这是可以做其他事情,而不是被挂起。由于TryEnterCriticalSection函数会更新CRITICAL_SECTION结构的某些成员,因此需要对应一个LeaveCriticalSection函数。

54/5<12345>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号