关于同步锁的问题,这是比较简单一个函数库,当然如果不习惯,也可以直接使用Mutex,应用waitforsingleobject,通过HANDLE的信号状态来保持对某一数据的原始操作。
锁主要的作用还是同步问题,简单来说就是防止多线程访问同一数据,如果不加同步,容易对数据造成破坏,一个可能达不到预期效果,一个可能数据操作时被打断。
同步锁,有临界点、mutex、信号量、事件。主要这里说的是临界锁,其他三种锁,都是HANDLE类型,
| Mutex | Critical Section |
性能和速度 | 慢。 Mutex 是内核对象,相关函数的执行 (WaitForSingleObject, ReleaseMutex)需要用户模式(User Mode)到内核模式 (Kernel Mode)的转换,在x86处理器上这种转化一般要 发费600个左右的 CPU指令周期。 | 快。 Critical Section本身不是内核对象,相关函数 (EnterCriticalSection,LeaveCriticalSection) 的调用一般都在用户模式内执行,在x86处理器上 一般只需要发费9个左右的 CPU指令周期。只有 当想要获得的锁正好被别的线程拥有时才会退化 成和Mutex一样,即转换到内核模式,发费600个 左右的 CPU指令周期。 |
能否跨越进程(Process)边界 | 可以 | 不可 |
定义写法 | HANDLE hmtx; | CRITICAL_SECTION cs; |
初始化写法 | hmtx= CreateMutex (NULL, FALSE, NULL); | InitializeCriticalSection(&cs); |
结束清除写法 | CloseHandle(hmtx); | DeleteCriticalSection(&cs); |
无限期等待的写法 | WaitForSingleObject (hmtx, INFINITE); | EnterCriticalSection(&cs); |
0等待(状态检测)的写法 | WaitForSingleObject (hmtx, 0); | TryEnterCriticalSection(&cs); |
任意时间等待的写法 | WaitForSingleObject (hmtx, dwMilliseconds); | 不支持 |
锁释放的写法 | ReleaseMutex(hmtx); | LeaveCriticalSection(&cs); |
能否被一道用于等待其他内核对象 | 可以(使用WaitForMultipleObjects, WaitForMultipleObjectsEx, MsgWaitForMultipleObjects, MsgWaitForMultipleObjectsEx等等) | 不可 |
当拥有锁的线程死亡时 | Mutex变成abandoned状态,其他的等待线程可以获得锁。 | Critical Section的状态不可知(undefined), 以后的动作就不能保证了。 |
自己会不会锁住自己 | 不会(对已获得的Mutex,重复调用WaitForSingleObject不会 锁住自己。但最后你别忘了要调用同样次数的 ReleaseMutex) | 不会(对已获得的Critical Section,重复调用 EnterCriticalSection不会锁住自己。但最后 你别忘了要调用同样次数的 LeaveCriticalSection) |
比较起来相对就简单点,然后比较简单,也比较快捷是临界锁,当然个人喜好和程序实现环境不一样,选取也就不一样了,
临界锁,简单来说,就是建立一个类,关于Critical_Section,在构造函数中初始化(Init),在析构函数中回收(delete),
然后建立两个对应函数锁和解锁函数,里面实现Enter和Leave,他的私有成员就是Critical_Section。如此,一个简单的临界锁就产生了,
当然,里面零件准备好了,还需要一个外部包装,就是Template《clsass Mutex》,用模板类,里面用临界锁类做私有成员。在构造函数中
初始化,然后调用锁函数,在析构里调用解锁函数。
template<class Obj>
class Lock
{
public:
Lock(Obj& pObj);
~Lock();
private:
Obj& m_obj;
}