
ccriticalsection是对关键段critical_section的封装。
关键段(critival section)是一小段代码,他在执行之前需要独占对一些共享资源的访问权。这种方法可以使多行代码以“原子形式”来对资源进行操控。这里的“原子形式”,指的是代码清楚除了当前线程之外没有其他任何线程会同时访问该资源。当然,系统一直可以暂停当前线程去调度其他线程。但是ccriticalsection 使用,在当前线程离开关键段之前,系统是不会去调度任何想要访问同一资源的其它线程的。
例如:如果两个线程同时访问一个链表,一个线程可能会在另一个线程搜寻元素的同时向链表中添加一个元素,将造成搜索结果不恰当;还有或许两个线程同时向链表中添加元素,这种状况会变的愈发混乱;甚至一个线程搜索的之后,另一个线程删除了递归节点,将直接造成程序崩溃。
解决这个难题,我们可以先在代码中定义一个CRITICAL_SECTION数据结构m_sect,然后把任何必须访问共享资源的代码放在entercriticalsection和LeaveCriticalSection之间。
EnterCriticalSection(&m_sect);
// 共享资源的代码段....
LeaveCriticalSection(&m_sect);
一个CRITICAL_SECTION结构如同是飞机上的一个卫生间,而厕所则是我们想要保护的资源(用EnterCriticalSection和LeaveCriticalSection组成的栅栏包围住“马桶”)。由于卫生间很小,因此在同一时刻只允许一个人在卫生间内使用厕所(在同一时刻只允许一个线程在关键段中使用被保护资源)。
如果有多个总是应该在一起使用的资源,那么我们可以把它们放到同一个“卫生间”中:只应该创建一个CRITICAL_SECTION结构来保护所有这种资源。

关于关键段,需要把握以下几点:
1、任何应访问共享资源的代码,都需要包括在EnterCriticalSection和LeaveCriticalSection之间。如果忘了哪怕是一个地方,共享资源就有也许被破坏。忘记调用EnterCriticalSection和LeaveCriticalSection,就似乎是未经许可就强行开启卫生间一样,线程试图开启并对资源进行操控。只要有一个线程有这样粗暴的行为,资源经常被破坏。
2、关键段CRITICAL_SECTION是个已公开的结构,因为Microsoft认为开发人员不需要理解这个构架的细节。对我们来说,不需要知道这个结构中的成员变量,我们绝对不需要在编写代码的之后用到他的成员。
3、为了对CRITICAL_SECTION结构进行操控,我们需要读取windows API函数,传入结构的地址。(注意是地址!)也就是说,如果该CRITICAL_SECTION结构生命周期没有结束,那么可以将该结构地址通过自己喜欢的任何形式传给任何线程。
4、在任何线程试图访问被保护的资源之前,必须对CRITICAL_SECTION结构的外部成员进程初始化。我们不知道内部成员,但可以读取Windows函数实现:VOID WINAPI initializecriticalsection(__out LPCRITICAL_SECTION lpCriticalSection);
5、当线程不再需要访问共享资源的之后,应调用以下的变量来清除该结构:VOID WINAPI DeleteCriticalSection(__inout LPCRITICAL_SECTION lpCriticalSection);
6、其实CRITICAL_SECTION并不知道什么是共享资源,也不会智能保护共享资源。其根本是,同一个时刻如果有多个线程调用EnterCriticalSection的之后,只有一个线程返回,其余线程则暂停执行,等待前面线程调用LeaveCriticalSection之后再执行。

7、可以看出,进入关键段是没有超时设置的,好像永远不会超时。实际上,对EnterCriticalSection的调用也会超时并导致异常。超时的时间长度由以下这个注册表子项中包括的CriticalSectionTimeout值决定:
HKEY_local_MACHINE\System\CurrentControlSet\Control\session Manager
这个值以秒为单位,他的默认值为2592000秒,大约30天。
8、同一个线程可以随意开启用一个关键段N次,也就是说同一个线程调用EnterCriticalSection无论几次都会返回。不同线程是否还能开启关键段,要看EnterCriticalSection的参数(CRITICAL_SECTION结构的地址)之前是否有线程处于过。要记住:飞机上的卫生间有多个,你可以随意开启无人的卫生间ccriticalsection 使用,不能进入有人的卫生间。
弄明白了CRITICAL_SECTION之后,使用CCriticalSection非常便利,如虎添翼。看代码:
//头文件
class CCriticalSection : public CSyncObjet
{...
public:
CRITICAL_SECTION m_sect;
public:
BOOL Unlock();
BOOL Lock();
BOOL Lock(Dword dwTimeout);
...
}

// 构造函数
CCriticalSection::CCriticalSection() : CSyncObject(NULL)
{
HRESULT hr = S_OK;
if (!InitializeCriticalSectionAndSpinCount(&m_sect, 0))//可以理解为InitializeCriticalSection,为了效率,加了一个旋转锁。
{
hr = HRESULT_FROM_WIN32(GetLastERROR());
}
if (FaiLED(hr))
{
Atlthrow(hr);
}
}
//进入关键段
BOOL CCriticalSection::Lock()
{
::EnterCriticalSection(&m_sect);
return TRUE;
}
// 离开关键段
BOOL CCriticalSection::Unlock()
{
::LeaveCriticalSection(&m_sect);
return TRUE;
}
// 析构

CCriticalSection::~CCriticalSection()
{
::DeleteCriticalSection(&m_sect);
}
爱淘宝的每天红包链接在那?爱淘宝红包怎么使用?
今天seo实验室小编要来帮大家讲述的内容是爱淘宝的每天红包链接在那?爱淘宝红包怎么使用?如果你们感兴趣的话,那就跟上小编我的脚
相机参数测量(camera calibration)及校正结果如何使用
一直都想写一写这个主题,但是,一直都感到有点虚,也没有去整理。在网上搜了一下,发现大多数都是转来转去,看着也是似懂非懂的,让人更老火
我的rokid的使用经验
备注:更多资料尽在开发者社区的文档中心 RokidOS开放源代码项目简介RokidOS是 Rokid领导的基于云端语音服
代理服务器的常见使用方式介绍(图文教程)
大多费尔公用模块都必须连接互联网,但有时可能由于网络问题而未能正常连接,这时可以尝试使用代理服务器。但首先您必需清楚代理服务
教您htc恢复出厂设定的使用步骤途径
恢复出厂设定这个功能并不是经常使用的,因为误操作造成的后果是相当严重的。恢复出厂设定从字面上就可以理解,手机中的所有更改将恢
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-135367-1.html
顶
中美双方在具有中国主权的南海上“合资”经营地区和平稳定
不强硬
发射DF21D和26