Windows线程同步--临界区对象(Critical Section Objects)

 

 

Windows线程同步--临界区对象(Critical Section Objects)

 

 

1.简介

 

       用于防止共享资源被同时访问,从而保证多线程安全。事件(Event)、互斥体(Mutex)、信号量(Semaphore)可以被用于进程间并行编程,但是临界区只能用于一个进程的线程中,而且在某一时刻,一个临界区对象只能被一个线程拥有。这样做的优点是提高了性能!

 

       旋转锁(Spin):在多核CPU中需要考虑个问题,临界资源可能正在被一个线程A使用,而同时另一个核中运行的线程B也想要这个资源,这时发现临界资源被占用,如果直接从运行状态转换成等待状态,这个转换需要消耗比如1000CPU时钟,而还未转换完时,也许线程A已经退出了临界区,势必造成CPU资源的浪费。所以微软给临界区增加了Spin,是个次数,让线程可以多次尝试进入临界区,减少转换的频率。这个问题在单核CPU系统中不用考虑,因为同一时刻只能有一个线程处于运行状态。

 

 

2.数据结构和方法

 

CRITICAL_SECTION

 

Windows系统中,当有一个资源(比如一个变量)要被多个线程使用时,需要声明一个CRITICAL_SECTION结构,用于存储临界区信息。

 

 

InitializeCriticalSection

CRITICAL_SECTION结构初始化一个临界区对象。

 

InitializeCriticalSectionAndSpinCount 

CRITICAL_SECTION结构初始化一个临界区对象,并可以传入一个Spin count,这个值在单核系统中会被忽略,在多核系统中在尝试spin count次之后还是进不了临界区才转成等待状态。

 

DeleteCriticalSection

删除指定的临界区对象

 

 

EnterCriticalSection

进入临界区,相当于PV操作中的P操作。会先判断是否能进入,不能则等待,即堵塞住(block)

 

 

TryEnterCriticalSection 

类似EnterCriticalSection,不同的时,如果无法进入,则立即返回,不堵塞住。返回值非零表示成功占有临界区;返回值为零表明临界区被其他线程占用。

 

 

LeaveCriticalSection

离开临界区,相当于PV操作中的V操作。

 

 

DeleteCriticalSection

释放掉被临界区占用的资源

 

 

3.常用封装

 

class CCritSec

{

     CRITICAL_SECTION m_CritSec;

 

     // make copy constructor and assignment operatorinaccessible

     CCritSec(const CCritSec &refCritSec);

     CCritSec &operator=(const CCritSec&refCritSec);

 

public:

     CCritSec() { InitializeCriticalSection(&m_CritSec); }

     ~CCritSec() { DeleteCriticalSection(&m_CritSec); }

     void Lock() { EnterCriticalSection(&m_CritSec);}

     void Unlock() { LeaveCriticalSection(&m_CritSec);}

};

 

 

class CAutoLock

{

     // make copy constructor and assignment operatorinaccessible

     CAutoLock(const CAutoLock &refAutoLock);

     CAutoLock &operator=(const CAutoLock&refAutoLock);

protected:

     CCritSec * m_pLock;

 

public:

     CAutoLock(CCritSec* plock)

     {

         m_pLock = plock;

         m_pLock->Lock();

     };

 

     ~CAutoLock() { m_pLock->Unlock(); }

};

 

 

这样大大简化了在多线程代码中对临界区对象的使用。

比如在类中声明一个成员变量:

CCritSec m_CritSec;

 

在访问公共变量(临街资源)的成员方法中加一句:

CAutoLock autoLock(&m_CritSec);

则相当于给这个的前后加了PV操作。从而实现互斥的访问临界资源

 

 

 

参考资料

 

http://msdn.microsoft.com/en-us/library/windows/desktop/ms682530(v=vs.85).aspx

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值