多线程编程经常遇到数据同步问题,通常的做法就是加锁,之前个人常用临界区(CTITICAL_SECTION),最近开发高效率程序,寻求更高效的同步方式,才有了对原子锁的研究。经测试,原子锁效率确实比临界区高,用数据衡量,原子锁的效率是临界区的5倍左右。
测试方法:
1、主线程加锁
2、工作线程等待
3、主线程解锁
4、工作线程结束等待
测试结果:测试3、4步骤之间的耗时,临界区耗时5~6微秒,原子锁耗时1~2微秒。
关于临界区和原子锁,请baidu看看相关文章,这里不多介绍了。注意原子锁不能嵌套使用,否则会被锁死,临界区没这个问题。
包装了两个类分别实现临界区(CLock)和原子锁(CLockAtom),同时包装了两个在作用域中方便使用的类(CLockRegion和CLockAtomRegion),具体使用见下面代码。
CLock类
#include <windows.h>
namespace UtilTool {
class CLock
{
public:
CLock(void)
{
InitializeCriticalSection(&cs);
}
~CLock(void)
{
DeleteCriticalSection(&cs);
}
inline void Lock()
{
EnterCriticalSection(&cs);
}
inline void UnLock()
{
LeaveCriticalSection(&cs);
}
private:
CRITICAL_SECTION cs;
};
class CLockRegion
{
public:
CLockRegion(CLock* lock) : m_lock(lock)
{
m_lock->Lock();
}
~CLockRegion()
{
m_lock->UnLock();
}
private:
CLock* m_lock;
};
}
CLockAtom类
#include <windows.h>
namespace UtilTool {
struct _UTILTOOL_IMPORT_EXPORT_TYPE_ CAtom
{
public:
CAtom()
{
m_l = 0;
}
volatile long* Get()
{
return &m_l;
}
private:
volatile long m_l;
};
//原子锁
//切忌嵌套使用
class CLockAtom
{
public:
CLockAtom(void)
{
m_ics = 0;
}
~CLockAtom(void){}
inline void Lock()
{
while (InterlockedExchange(&m_ics, 1) == 1)
{
Sleep(0);
}
}
inline void UnLock()
{
InterlockedExchange(&m_ics, 0);
}
static inline void Lock(CAtom* pAtom)
{
while (InterlockedExchange(pAtom->Get(), 1) == 1)
{
Sleep(0);
}
}
static inline void UnLock(CAtom* pAtom)
{
InterlockedExchange(pAtom->Get(), 0);
}
private:
volatile long m_ics;
};
class CLockAtomRegion
{
public:
CLockAtomRegion(CLockAtom* lock)
{
m_atom = NULL;
m_lock = lock;
m_lock->Lock();
}
CLockAtomRegion(CAtom* atom)
{
m_atom = atom;
m_lock = NULL;
CLockAtom::Lock(m_atom);
}
~CLockAtomRegion()
{
if (m_lock)
{
m_lock->UnLock();
}
else if (m_atom)
{
CLockAtom::UnLock(m_atom);
}
}
private:
CLockAtom* m_lock;
CAtom* m_atom;
};
}
CLockRegion的用法,CLockAtomRegion类似
CLock lock;
void MyFunc()
{
//进入函数,_lock被创建,调用CLockRegion构造函数,加锁
CLockRegion _lock(&lock);
//do something
//函数退出,_lock被析构,解锁
}