一、基本概念
在数据库中,对某数据的两个基本操作为写和读。分布有两种锁控制:排它锁(X锁)、共享锁(S锁)。
排它锁(x锁):若事务T对数据D加X锁,则其他不论什么事务都不能再对D加不论什么类型的锁。直至T释放D上的X锁;
一般要求在改动数据前要向该数据加排它锁,所以排它锁又称为写锁。
共享锁(s锁):若事务T对数据D加S锁。则其他事务仅仅能对D加S锁,而不能加X锁,直至T释放D上的S锁;
一般要求在读取数据前要向该数据加共享锁。 所以共享锁又称读锁。
程序所收到的请求包含下面五种:Start、End、XLock、SLock、Unlock
Start:开启对应的事件请求
End: 关闭对应的事件请求
XLock: 对数据对象D加入X锁。进行写操作(当事件以对数据A加入S锁时,此时可升级为X锁)
SLock: 对数据对象D加入S锁,进行读操作
Unlock: 对数据对象D进行解锁(对数据D的X/S锁解绑。并检查等待队列)
本程序并不进行死锁检測以及死锁预防。对于等待队列採取FIFO原则进行。
二、数据结构
读写锁维护一个数据D的状态表,标记当前数据D的实时状态,锁表的信息随着事务的运行动态更新,反映当前的锁状态。
其数据结构例如以下图所看到的:
当中:mObjectList:为map结构的对象树。可方便高速查找对应对象。
objectName:为对象数据D的名称
curXLockTrans: 为当前写操作的事件
waitingTransList: 为写等待队列
shareList: 为共享集(当curXLockTrans不为空时,变为共享等待队列)
事件ID的数据结构例如以下:
当中:mTransId: 为map结构的事件树。能够高速的查找对应事件
tranId: 为事件名称
curLockObjList: 为此事件眼下所操作的对象列表
三、源码
本程序为所的锁管理接口。所以封装成类。方便程序调用。程序源代码能够点击这里下载。
数据结构例如以下:
class LMer {
private:
struct object
{
string objectName;
string curXLockTrans;
queue waitingTransList;
set shareList;
};
struct transId
{
string tranId;
set curLockObjList;
};
map mObjectList;
map mTransId;
public:
LMer(){}
string LMer::handleInput(vector& vInput);
void LMer::handleAction(string sAction, transId* trId, object* obj, string& result);
void LMer::diviTransID(transId* trId, object* pObj, string& result);
};逻辑结构实现例如以下:
string LMer::handleInput(vector& vInput)
{
string result = "";
//二參数输入
if (vInput.size() == 2)
{ //进程存在,进入下一步
map::iterator transIt = mTransId.find(vInput[1]);
if (transIt != mTransId.end())
{
//是否结束事件(结束事件队列中全部事件)
if (vInput[0] == "End")
{
result += "\tTransaction "+ vInput[1] +" ended\n\t\t\t";
//解绑进程全部事物
set::iterator obj_index;
while(transIt->second->curLockObjList.size() != 0)
{
obj_index = transIt->second->curLockObjList.begin();
diviTransID(transIt->second, *obj_index, result);
}
//清空请求事件
mTransId.erase(transIt);
}
}
else if(vInput[0] == "Start")//为start,创立进程
{
transId* pTransId = new transId();
pTransId->tranId = vInput[1];
//将此进程增加进程树中
mTransId[vInput[1]] = pTransId;
result += "Transaction " + vInput[1] +" started\n";
}
}
else //三參数输入
{ //创建新操作对象
if(mObjectList.find(vInput[2]) == mObjectList.end())
{
object* pObjectIndex = new object();
pObjectIndex->objectName = vInput[2];
pObjectIndex->curXLockTrans = "";
mObjectList[vInput[2]] = pObjectIndex;
}
if (vInput[0] == "Unlock")
{
//解锁trans->obj
diviTransID(mTransId[vInput[1]], mObjectList[vInput[2]], result);
}
else//进行常规处理(Xlock、Slock)
{
//进行处理
handleAction(vInput[0], mTransId[vInput[1]], mObjectList[vInput[2]], result);
}
}
return result;
}
void LMer::handleAction(string sAction, transId* trId, object* obj, string& result)
{
//检查是否有占用
if (sAction == "SLock")
{
if (obj->curXLockTrans == "")
{
obj->shareList.insert(trId->tranId);
trId->curLockObjList.insert(obj);
result += "S-Lock granted to "+ trId->tranId +"\n";
}
else//被占用
{
obj->shareList.insert(trId->tranId);
result += "Waiting for lock (X-lock held by: "+ obj->curXLockTrans +")\n";
}
}
else if(sAction == "XLock")
{
//未有写操作
if (obj->curXLockTrans == "")
{
int shareNum = obj->shareList.size();
if (shareNum > 1)
{
string sTemp = "";
for (set::iterator it_index = obj->shareList.begin();
it_index != obj->shareList.end(); it_index++)
{
sTemp += " " + *it_index;
}
obj->waitingTransList.push(trId->tranId);
result += "Waiting for lock (S-lock held by:" + sTemp + "\n";
}
else if (shareNum == 1)
{
//update
if (*(obj->shareList.begin()) == trId->tranId)
{
obj->curXLockTrans = trId->tranId;
obj->shareList.clear();
result += "Upgrade to XLock granted\n";
}
else
{
obj->waitingTransList.push(trId->tranId);
result += "Waiting for lock (S-lock held by:" + *(obj->shareList.begin()) + ")\n";
}
}
else if (shareNum == 0)
{
obj->curXLockTrans = trId->tranId;
trId->curLockObjList.insert(obj);
result += "XLock granted\n";
}
}
else//当前存在写操作
{
obj->waitingTransList.push(trId->tranId);
result += "Waiting for lock (X-lock held by: "+ obj->curXLockTrans +")\n";
}
}
}
void LMer::diviTransID(transId* trId, object* pObj, string& result)
{
if(pObj->curXLockTrans != "")
{
//对写操作解绑
if (pObj->curXLockTrans == trId->tranId)
{
pObj->curXLockTrans = "";
trId->curLockObjList.erase(pObj);
result += "Lock released\n\t\t\t";
}
else
{
result += "I can not find the transaction.\n\t\t\t";
}
}//对共享读集合解绑
else
{
set::iterator shareIndex = pObj->shareList.find(trId->tranId);
if (shareIndex != pObj->shareList.end())
{
pObj->shareList.erase(shareIndex);
trId->curLockObjList.erase(pObj);
result += "Lock released\n\t\t\t";
}
else
{
result += "I can not find the transaction.\n\t\t\t";
}
}
//查看写等待队列
if (pObj->waitingTransList.size() != 0)
{
pObj->curXLockTrans = pObj->waitingTransList.front();
pObj->waitingTransList.pop();
result += "X-Lock on "+ pObj->objectName +" granted to "+ pObj->curXLockTrans +"\n";
}//查看共享队列
else if (pObj->shareList.size() != 0)
{
string temp = "";
for(set::iterator it_index = pObj->shareList.begin();
it_index != pObj->shareList.end(); it_index++)
{
temp += " " + *it_index;
}
result += "S-Lock on "+ pObj->objectName +" granted to "+ temp +"\n";
}
}
四、程序执行
程序数据输入例如以下:
执行后得到结果例如以下: