I. Basic Concepts
In a database, the two basic operations on a data are write and read. The distribution has two types of lock control: exclusive lock (X lock) and shared lock (S lock ).
Exclusive lock (x lock): If transaction T adds X lock to data D, no other transaction can apply any type lock to D Until T releases the X lock on D;
Generally, an exclusive lock must be applied to the data before the data is modified. Therefore, an exclusive lock is also called a write lock.
Share lock (s lock): If transaction T adds S lock to data D, other transactions can only apply S lock to D instead of X lock, until T releases the S lock on D;
Generally, you need to apply a shared lock to the data before reading the data. Therefore, a shared lock is also called a read lock.
The program receives the following five types of requests: Start, End, XLock, SLock, and Unlock.
Start: Enable the corresponding event request
End: closes the corresponding event request.
XLock: add the X lock to the Data Object D and perform the write operation (when the event adds the S lock to the data a, it can be upgraded to the X lock)
SLock: adds the S lock to the Data Object D for read operations.
Unlock: Unlock the Data Object D (unbind the X/S lock of the Data D and check the waiting queue)
This program does not perform Deadlock Detection and deadlock prevention. It adopts the FIFO principle for waiting queues.
Ii. Data Structure
Read/write locks maintain a data D status table, marking the real-time status of the current data D. The information of the lock table is dynamically updated with the execution of the transaction, reflecting the current lock status.
Shows the data structure:
Here: mObjectList: indicates the Object Tree of the map structure, which allows you to quickly find the corresponding object.
ObjectName: name of object data D
CurXLockTrans: The current write operation event.
WaitingTransList: Write wait queue
ShareList: shared set (when curXLockTrans is not empty, it becomes a shared waiting queue)
The data structure of the event ID is as follows:
Where: mTransId: indicates the event tree in the map structure. You can quickly find the corresponding event.
TranId: event name
CurLockObjList: list of objects currently operated for this event
Iii. Source Code
This program is the lock management interface, so it is encapsulated into a class to facilitate program calls. Click here to download the program source code.
The data structure is as follows:
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);};
The logical structure is implemented as follows:
String LMer: handleInput (vector <string> & vInput) {string result = ""; // if (vInput. size () = 2) {// process exists, go to the next map <string, transId * >:: iterator transIt = mTransId. find (vInput [1]); if (transIt! = MTransId. end () {// whether to End the event (all events in the end event queue) if (vInput [0] = "End ") {result + = "\ tTransaction" + vInput [1] + "ended \ n \ t"; // unbind all processes from the set <object *> :: iterator obj_index; while (transIt-> second-> curLockObjList. size ()! = 0) {obj_index = transIt-> second-> curLockObjList. begin (); diviTransID (transIt-> second, * obj_index, result);} // clear the request event mTransId. erase (transIt) ;}} else if (vInput [0] = "Start") // start, creation process {transId * pTransId = new transId (); pTransId-> tranId = vInput [1]; // Add this process to the process tree. mTransId [vInput [1] = pTransId; result + = "Transaction" + vInput [1] + "started \ n" ;}} else // input three parameters {// create a new operation object 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 ") {// unlock trans-> obj diviTransID (mTransId [vInput [1], mObjectList [vInput [2], result );} else // perform regular processing (Xlock, Slock) {// handle handleAction (vInput [0], mTransId [vInput [1], mObjectList [vInput [2], result) ;}} return result;} void LMer: handleAction (string sAction, transId * trId, object * obj, string & result) {// check whether there is any occupied if (sAction = "SLock") {if (obj-> curXLockTrans = "") {obj-> shareList. insert (trId-> tranId); trId-> curLockObjList. insert (obj); result + = "S-Lock granted to" + trId-> tranId + "\ n";} else // occupied {obj-> shareList. insert (trId-> tranId); result + = "Waiting for lock (X-lock el D by: "+ obj-> curXLockTrans +") \ n ";}} else if (sAction =" XLock ") {// No write operation if (obj-> curXLockTrans = "") {int partition num = obj-> shareList. size (); if (interval num> 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 + "\ n";} else if (interval num = 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-> tran Id); result + = "Waiting for lock (S-lock held by:" + * (obj-> shareList. begin () + ") \ n" ;}} else if (partition num = 0) {obj-> curXLockTrans = trId-> tranId; trId-> curLockObjList. insert (obj); result + = "XLock granted \ n" ;}} else // The current write operation {obj-> waitingTransList. push (trId-> tranId); result + = "Waiting for lock (X-lock held by:" + obj-> curXLockTrans + ") \ n ";}}} void LMer: diviTransID (transId * trId, objec T * pObj, string & result) {if (pObj-> curXLockTrans! = "") {// Unbind if (pObj-> curXLockTrans = trId-> tranId) {pObj-> curXLockTrans = ""; trId-> curLockObjList. erase (pObj); result + = "Lock released \ n \ t";} else {result + = "I can not find the transaction. \ n \ t ";}// unbind else from the shared read set {set <string >:: iterator specified index = pObj-> shareList. find (trId-> tranId); if (trans index! = PObj-> shareList. end () {pObj-> shareList. erase (partition index); trId-> curLockObjList. erase (pObj); result + = "Lock released \ n \ t";} else {result + = "I can not find the transaction. \ n \ t ";}}// view the write wait queue if (pObj-> waitingTransList. size ()! = 0) {pObj-> curXLockTrans = pObj-> waitingTransList. front (); pObj-> waitingTransList. pop (); result + = "X-Lock on" + pObj-> objectName + "granted to" + pObj-> curXLockTrans + "\ n ";} // view the shared queue 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 + "\ n ";}}
4. program running
Program data input is as follows:
The result is as follows: