一、基本概念
在数据库中,对某数据的两个基本操作为写和读,分布有两种锁控制:排它锁(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 逻辑结构实现如下:
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