Hello I have a minor question about locking. We need to use the wait() method in our lock method somewhere. Suppose I use a collection (lockedSet) to store locked records and check if this collection is empty before adding the record, else it waits. Ignoring exceptions:
Now if it goes into wait, will it still add the record after wait (line 2) or I need to add in line 6 manually?
I asked this because when I run isLocked method it returns false!!!
I don't really understand your code. Your comment states that you "check if this collection is empty before adding the record", however your code does exactly the opposite: "if (! lockedSet.isEmpty())"
I also don't understand why your collection needs to be empty before you can add a record. Isn't it desirable that someone can lock record 7 at the same time someone else locks record 9? In which case, wouldn't both those numbers be added to the collection?
You really must put your check for whether the the individual record is currently locked inside a loop of some kind. Ignoring the problem above, with your current code we have the potential situation that:
Since notifyAll() was called, both thread B and thread C received the notification, and now both thread B and thread C think that they have the record locked!
Change the logic to a loop and you avoid this potential problem.
Note: I have not given a solution here because I believe it is one of the most fundamental issues you must understand in the project, and just giving away a solution will not help readers understand the issue. If you have any questions at all, please ask!
The idea is really only allow one write thread to do update/delete. So I thought of making sure the lockSet is empty before the record can be added and becomes locked.
Now my original testing was if the lockSet IS NOT empty, it waits. But after the wait completes, does the code finish without adding the record or will it also add the record automatically?
From my testing code, when I printed out isLocked, it can be false which seems not right - how can lockSet need have record and allow update/delete? So that's why do I need to manually add in the &quot;lockSet.add(recNo)&quot; line after wait?
Also from Andrew's given scenario: Threads B and C should not able to both lock record 5 at the same time. Because if B and C do successfully lock record 5, B updates customer ID "11111" and C updates customer ID "44444" then on the data level it's inconsistent. Of course in my app it does check if the customer ID is already filled in before updating.
K. Tsang wrote:do I need to manually add in the "lockSet.add(recNo)" line after wait?
Yes you do. When you call "wait()" the tread blocks at that particular line in the code. When you later call "notify" or "notifyAll" the execution of that code resumes at the point where it had been blocked. So it will resume at line 6 - it does not have any way of knowing any other line number you might prefer to go back to.
K. Tsang wrote:Also from Andrew's given scenario: Threads B and C should not able to both lock record 5 at the same time.
We are both in agreement about that, however my issue is that I believe your code will allow both threads B and C to lock record 5 simultaneously.
My code is a little odd, simply because I am cheating with the unlocking of the record, but it should look familiar to you:
Now look at the output:
With no particular reason, thread C happened to get the lock first at 13:41:26. Threads A & B also attempted to get the lock mere milliseconds behind thread C, but they were too late. So they got blocked for 5 seconds while thread C does it's work.
Thread C finished it's work at 13:41:31 and called notifyAll. This resulted in Thread A waking up and getting the lock, and within milliseconds thread B woke up and also got the lock.
Threads B and C then continued to work simultaneously, both believing that they own the one true lock. They both finished simultaneously at 13:41:36.
Feel free to modify my "Tsang" class to call your lock and unlock methods as appropriate, and test with your system. I believe you will find that multiple threads can own the same lock simultaneously.