乐观锁就是尽量让大家共享使用资源,当真的发生了资源的重要改变的时候,才给共享使用资源的所以线程一个通知,收到通知的线程回滚之前的行为。乐观锁通常在数据库使用,数据库大概比较适合回滚吧。
一般程序代码里面可能很难回滚,所以通常不适用。
但扩展一下概念,比如 new 一个指针变量,传递给多个线程。里面可能都会使用它,但只能有一个线程可以释放它,但不知道是哪个线程。当然,这里假设new 这个指针的地方 并不适合delete(多线程程序里,可能有时候有些地方会出现这种情况)。 那么每个使用指针的线程 其实都需要关注指针是否被释放了,如果被释放了还在使用的话 就会出现访问错误。 同样的, 准备删除这个指针的线程,是否可以马上删除它?不可以,所以删除前必须给一个通知,收到通知的线程都会停止访问该指针了。
所以以上这种情况,所有线程都乐观访问了资源,直到收到通知才释放锁(释放锁即为放弃资源使用权),通知完成的线程最后清理锁。
实现代码如下:
class OptLock{
public:
OptLock()
:m_iCount(0){
}
// 加锁 ,计数加1
unsigned int Lock()
{
int old = m_iCount ;
while(old == InterlockIncrease(&m_iCount))
{
old = m_iCount;
}
return m_iCount;
}
//解锁, 计数减1
unsigned int Unlock()
{
unsigned int old = m_iCount ;
if(old == 0)
return 0;
while(old == InterlockDecrease(&m_iCount))
{
old = m_iCount;
}
return m_iCount;
}
//高位设置 1 ,表示通知
int Notify()
{
unsigned int mask = 0x0001ffff;
volatile unsigned int newcount = m_iCount&mask ;
unsigned int old = m_iCount;
while(::InterlockedCompareExchange(m_iCount,newcount,old) == old)
{
newcount = m_iCount&mask ;
old = m_iCount;
}
return 0;
}
//判断该锁是否有重大变化 ,如果true,表示要尽快释放锁资源
bool IsNotify() const
{
return (m_iCount>>16)
}
// 判断是否拥有该锁的线程是否都释放完成了
bool IsAllRelease()
{
unsigned int mask = 0x0000ffff;
if(IsNotify())
{
return (mask& m_iCount==0);
}
}
private:
volatile unsigned int m_iCount;
};
使用方法如下:
OptLock g_Lock;
读取指针
UINT ThreadFunA(LPVOID pVoid)
{
if(g_Lock.IsNotify()==false)
{
g_Lock.Lock();
Int* p = (int*) pVoid;
......
if(g_Lock.IsNotify())
{ //马上退出
g_Lock.UnLock;
return 0;
}
.....................
g_Lock.UnLock();
}
return 0;
}
// 删除线程
UINT ThreadFunB (LPVOID pvoid )
{
if(g_Lock.IsNotif()
{
g_Lock.Lock();
int * p = (int*) pvoid ;
......
// 准备删除指针了
g_Lock.Notify();
while( IsAllRelease () == false) {};
g_Lock.UnLock();
delete p ;
}
}