如何打一把好锁

微软在windows 3.1以后,便引入了多线程模型,相对于单线程模型中只有一个线程主动放弃CPU(等待资源或执行完毕)的单一执行模式,多线程的出现在很大程度上提高了程序的运行效率和响应度。但是多线程的并发执行也带来了一个大问题:共享数据的不一致。因此,在多线程编程中,需要加锁来同步协调线程间的协作,保证数据执行的一致性。在windows中,常见的锁包括互斥量(mutex)、信号量(semaphore)和事件(event)。当然,锁的实现有很多种形式,你可以自己写一个P、V原语类,也可以调用windows的API,也可以在windows的API上做一层封装以避免加锁、解锁不成对(原因有很多种,比如临界区中return了或者抛出了异常等)。那么,就来封装一个自己的类吧!

注意看,这里使用了设计模式中的策略模式,根据传入的锁的不同,构造出不同的锁对象。其中,抽象类是CAutoObject,然后三种不同的具体锁类:临界区、互斥量和事件继承CAutoObject。接着,在CAutoLock(锁的工厂)的构造函数中传入具体的锁对象,构造出具体种类的锁。


//
// 自动锁对象基类,不可实例化
//
class CAutoLockObject
{
    CAutoLockObject(const CAutoLockObject &);
    CAutoLockObject& operator=(const CAutoLockObject &);    
public:
    CAutoLockObject(){}
   
    virtual ~CAutoLockObject(){}


    virtual void Lock()PURE;
    virtual void Unlock()PURE;
};


//
//自动锁管理类
//
class CAutoLock
{
//没有默认构造
    CAutoLock();
//没有基于对象的构造
    CAutoLock(const CAutoLock &);
//不允许=赋值
    CAutoLock& operator=(const CAutoLock &);
    
//同步对象
CAutoLockObject & m_SyncObject;


public:
    CAutoLock(CAutoLockObject &SyncObject):m_SyncObject(SyncObject)
    {
        m_SyncObject.Lock();
    }
    
    virtual ~CAutoLock()
    {
        m_SyncObject.Unlock();
    };
};
//评论:将加锁、解锁过程放在构造函数和析构函数中有一点好处,这样可以保证构造一个锁对象的时候自动上锁,然后对象析构的自动解锁,从而避免了加锁解锁不一致的情况。

//
//锁:临界区
//
class CAutoLockCriticalSection : public CAutoLockObject
{
  //没有基于对象的构造
   CAutoLockCriticalSection(const CAutoLockCriticalSection &);
//不允许=赋值
   CAutoLockCriticalSection& operator=(const CAutoLockCriticalSection &); 

//同步对象
    CRITICAL_SECTION m_cs;
public:
    CAutoLockCriticalSection()
{
        InitializeCriticalSection(&m_cs);
}


    virtual ~CAutoLockCriticalSection()
    {
        DeleteCriticalSection(&m_cs);
    }


    virtual void Lock()
    {
        EnterCriticalSection(&m_cs);
    }


    virtual void Unlock()
    {
        LeaveCriticalSection(&m_cs);
    }


};


//
//锁:互斥
//
class CAutoLockMutex : public CAutoLockObject
{
//没有基于对象的构造
    CAutoLockMutex(const CAutoLockMutex &);
//不允许=赋值
    CAutoLockMutex& operator=(const CAutoLockMutex &);

//同步对象
HANDLE m_hMutex;


public:
CAutoLockMutex(LPCTSTR lpMutexName)
{
m_hMutex = CreateMutex(NULL, TRUE,lpMutexName);
}
virtual ~CAutoLockMutex()
{
CloseHandle(m_hMutex);
}


virtual void Lock()
{
WaitForSingleObject(m_hMutex,INFINITE);
}
virtual void Unlock()
{
ReleaseMutex(m_hMutex);
}
};


//
//锁:Event事件
//
class CAutoLockEvent : public CAutoLockObject
{
//没有基于对象的构造
CAutoLockEvent(const CAutoLockEvent &);
//不允许=赋值
CAutoLockEvent& operator=(const CAutoLockEvent &);


//同步对象
HANDLE m_hEvent;


public:
CAutoLockEvent(LPCTSTR lpEventName)
{
m_hEvent = CreateEvent(NULL, FALSE, TRUE, lpEventName);
}
virtual ~CAutoLockEvent()
{
CloseHandle(m_hEvent);
}


virtual void Lock()
{
WaitForSingleObject(m_hEvent,INFINITE);
}
virtual void Unlock()
{
SetEvent(m_hEvent);
}
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值