Dhirendra
1. The lock() and unlock() method that we must implement are to ensure that database transaction is ATOMIC and CONSISTENT (ACID standard). This lock() is to be held against a specific record or against ALL records of the database.
2. The lock that a thread must acquire when executing a synchronized method, is a built-in core feature of the
java language. This lock/monitor is obtained by a thread, on an Object (not a database record). A thread may synchronize on 'this' object or any other object. It ensures that no other thread which needs a lock on the SAME object runs concurrently.
If we adopt a bad design, the lock mentioned in point2 will suffice, and we would not need the lock mentioned in point1. This is possible if for every single ATOMIC transaction that a client can perform against the database, a single synchronized method() is defined in the database. For eg. we may defined a synchronized book() function within the data class. In such case there is no need to implement lock() and unlock() as mentioned in point1.
Unfortunately we can't place client-side logic in the database. The database has to remain generic. The client-side logic must remain on the client-local or remote.
So we must put an operation like book() on the client-side and implement it by calling the generic read/write methods of the data object.
Now consider what an ATOMIC book() operation involves:-
1. Read operation to find the number of seats available.
2. Check if seats requested <= seats available
3. If condition 2 is true then make write operation on database to reserve seats, decrementing available seats by 2.
Consider this scenario:-
Client1 wants to book 2 seats on a Flight (= a specific database record). Client1 executes Step1 to find the number of available seats. Client1 receives the return which shows that the number of available seats which is 2.
Just after Client1 executes Step1 (and before it executes Step3), another Client2 also executes against the same record (i.e. same flight) and books 2 seats.
Thereafter Client1 takes step2 and Step3, without knowing that Client2's actions have rendered the condition found in Step1 untrue. Here a write action to reserve non-existent seats may leave the database in an INCONSISTENT state.
It is thus clear that we need to externally implement a lock which fulfills the following conditions:-
1. It exists against a specific record (or ALL records),
2. It can live/survive across the several method calls necessary to implement a single ATOMIC transaction.
3. It is granted only to one client at a time for a given record.
Then the inconsistency mentioned in the above scenario would not occur if the clients follow a lock/unlock protocol to implement an ATOMIC transactions that involves database modification.
Thus Client1 should acquire a lock before executing Step1 and then release the lock after executing Step3.
It is thus guaranteed that while Client1 holds a lock against a record, Client2 cannot acquire a lock against the same record. This in turn guarantees that Client2 cannot modify the record until Client1 has completed its ATOMIC transaction and released the lock.