Hello, My DBMain interface has 3 methods. // Locks a record so that it can only be updated or deleted by this client. // If the specified record is already locked, the current thread gives up // the CPU and consumes no CPU cycles until the record is unlocked. public void lock(int recNo) throws RecordNotFoundException; // Releases the lock on a record. public void unlock(int recNo) throws RecordNotFoundException; // Determines if a record is currenly locked. Returns true if the // record is locked, false otherwise. public boolean isLocked(int recNo) But there is no parameter to define clientID. How must I do locking on clientID? If a change DBMain interface I will automatically fall. Can someone help me? Baris (Holland)
Hi Baris, Welcome to JavaRanch and this forum! I think that many people on this forum use the Data instance as the lock owner. It works well as far as each client owns its own instance of Data (and as the app is single table of course). In other words, "this" in your lock methods may represent the client. Regards, Phil.
Hoi Baris, Welcome to JavaRanch and this forum. Just to expand on Phil's comment a bit... If you create an instance of the Data class for each client, then you can use the instance itself as the client identifier (as Phil suggested). This implies that your network server will actually have a factory creating instances of connections. This implies a level of indirection when connecting to your server. Regards, Andrew
Hi Baris, I suggest you think about why you need locking - once you have that sorted out, you will probably be able to work out which calls to which methods need to be called from within a locked context. The basic problem is what happens when two clients try to update the same record:
Client A reads record 1 - sees that it is available
Client B reads record 1 - sees that it is available
Client A gets customer number from the end user
Client B gets customer number from the end user
Client A updates record 1 with the customer number
Client B updates record 1 with the customer number
So the question is - how can locking help you to solve that particular problem? I will let you have a think about that (and post your thoughts) before going further. Regards, Andrew
Hi Andrew, I think this problem can be solved by locking record 1 by Client A. When this record is locked, it can't be used by Client B. When Client A finishes his job, he must release the lock on record 1 so Client B can use this record. But this record is allready updated by Client A. So after locking Client B must check again if record 1 is still available. I think I will implement as next:
Must I synchronize whole array or just that item inside the array? Thanks Regards, Baris
I think this problem can be solved by locking record 1 by Client A. When this record is locked, it can't be used by Client B. When Client A finishes his job, he must release the lock on record 1 so Client B can use this record. But this record is allready updated by Client A. So after locking Client B must check again if record 1 is still available.
That sounds a good way to handle it. So you can now see the answer to your original question ("By which methods shall I use locking?") - it depends on the usage of the method whether it is called while you own a lock or not. If all you are doing is reading a record to display to the client, you do not need to lock the record first. But if you are reading the record to verify whether it is still available before an update then you need to own the lock.
I think I will implement as next:
Your text description says that you will handle the problem by using the lock methods, but the code you provided shows you using synchronization to handle the problem. Synchronization could handle the same problem, however it causes two new problems:
Reduction in concurrency. There is quite a lot of work within that synchronized block - you are reading data from the disk, converting it into fields, validating the fields, updating the fields, converting it back into the disk format, and updating the record. While all this is happening, you have blocked all other access to the mutex. This is not such a big problem since your mutex appears to be specific to each individual record, but it is still an issue. It is much better to reduce the length of time your thread owns any mutex. So your lock() method will either be synchronized or contain a synchronized block. But as soon as the lock method returns, you are out of the synchronized block. This leaves the mutex free for other threads.
The entire book() method must be on the database server. You may choose to have your book() method on the server if you feel that it meets your requirements, however this is not what you are doing. Your design forces the book method to be on the server. (By the way, you may want to look at the thread "Should lock methods be callable by the client for some ideas about whether the book method should be on the server or not. But even in that thread you will notice that most people are talking about whether to have the book method in the client tier or the middleware tier - they are not talking about having it on the database tier.) With what you are doing, it becomes more difficult to later change the design. If the client wanted to go to three physical tiers, or have the book() method in the client, they could not do it without a major rewrite of sections of your code.