• 数据库读写锁的实现(C++)


    一、基本概念

    在数据库中,对某数据的两个基本操作为写和读。分布有两种锁控制:排它锁(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<string> waitingTransList;
            set<string> shareList;
        };
    
        struct transId
        {
            string   tranId;
            set<object*>  curLockObjList;
        };
    
        map<string, object*> mObjectList; 
        map<string, transId*> mTransId;
    
    public:
        
        LMer(){}
        string LMer::handleInput(vector<string>& 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<string>& vInput)
    {
        string result = "";
        //二參数输入
        if (vInput.size() == 2)
        {    //进程存在,进入下一步
            map<string, transId*>::iterator transIt = mTransId.find(vInput[1]);
            if (transIt != mTransId.end())
            {
                //是否结束事件(结束事件队列中全部事件)
                if (vInput[0] == "End")
                {
                    result += "	Transaction "+ vInput[1] +" ended
    			";
                    //解绑进程全部事物
                    set<object*>::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
    ";
            }
        }
        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 +"
    ";
            }
            else//被占用
            {
                obj->shareList.insert(trId->tranId);
                result += "Waiting for lock (X-lock held by: "+ obj->curXLockTrans +")
    ";
            }
        }
        else if(sAction == "XLock")
        {
            //未有写操作
            if (obj->curXLockTrans == "")
            {
                int shareNum = obj->shareList.size();
                if (shareNum > 1)
                {
                    string sTemp = "";
                    for (set<string>::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 + "
    ";
                }
                else if (shareNum == 1)
                {
                    //update
                    if (*(obj->shareList.begin()) == trId->tranId)
                    {
                        obj->curXLockTrans = trId->tranId;
                        obj->shareList.clear();
                        result += "Upgrade to XLock granted
    ";
                    }
                    else
                    {
                        obj->waitingTransList.push(trId->tranId);
                        result += "Waiting for lock (S-lock held by:" + *(obj->shareList.begin()) + ")
    ";
                    }
                }
                else if (shareNum == 0)
                {
                    obj->curXLockTrans = trId->tranId;
                    trId->curLockObjList.insert(obj);
                    result += "XLock granted
    ";
                }
            }
            else//当前存在写操作
            {
                obj->waitingTransList.push(trId->tranId);
                result += "Waiting for lock (X-lock held by: "+ obj->curXLockTrans +")
    ";
            }
        }
    }
    
    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
    			";
            }
            else
            {
                result += "I can not find the transaction.
    			";
            }
        }//对共享读集合解绑
        else 
        {
            set<string>::iterator shareIndex = pObj->shareList.find(trId->tranId);
            if (shareIndex != pObj->shareList.end())
            {
                pObj->shareList.erase(shareIndex);
                trId->curLockObjList.erase(pObj);
                result += "Lock released
    			";
            }
            else
            {
                result += "I can not find the transaction.
    			";
            }
        }
        //查看写等待队列
        if (pObj->waitingTransList.size() != 0)
        {
            pObj->curXLockTrans = pObj->waitingTransList.front();
            pObj->waitingTransList.pop();
            result += "X-Lock on "+ pObj->objectName +" granted to "+ pObj->curXLockTrans +"
    ";
        }//查看共享队列
        else if (pObj->shareList.size() != 0)
        {
            string temp = "";
            for(set<string>::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 +"
    ";
        }
    }

    四、程序执行

    程序数据输入例如以下:



    执行后得到结果例如以下:




  • 相关阅读:
    华为面向开发者的十大技术
    为什么开发者应该摒弃敏捷?
    程序员创业的特别之处
    这是我的facebook和twitter,欢迎大家来加我
    教程:2014新版新浪博客如何添加音乐播放器?
    Algs4-1.1.11编写一段代码,打印出一个二维布尔数组的内容
    Algs4-1.1.9十进制整数转二进制
    Algs4-1.1.8下列语句会打印出什么结果?给出解释
    Algs4-1.1.7分别给出以下代码段打印的值
    Algs4-1.1.6下面这段程序会打印出什么
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/6794914.html
Copyright © 2020-2023  润新知