I find it difficult to continue:banghead:. I need a Lock register to keep a record of each lock. When a thread tries to lock an already locked record, the thread must behave as following requirement.
Any attempt to lock a resource that is already locked should cause the current thread to give up the CPU, consuming no CPU cycles until the desired resource becomes available.
If I use FileLock, then that's a nature thing, but without it, it seems to me that I need to read out the record from database file and put it in an object and then somehow lock it.
Can you not synchronize on the database object you have created
and thereby wait for its lock to become available? This would let
the JVM do the work. Please elaborate further on the problem.
When a record is locked, the recNo is added to this map; when a record is unlocked, the recNo is removed from the map. And when a record is already in the map, the thread goes moves into the waiting state. And you could use this map to make lock/unlock methods thread-safe.
That's the confusing point. If I call wait(), it has to been in a synchronized block of "an object", and what's the object?
We have three options: the Data object, the Map or the Record object.
If we choose Data, it works, so at any time only one thread can lock the Data. Those failed to lock the record (found RecNo in the Map) have to wait for next turn to lock the Data and then call lock(), if found the records still there, then wait again.
If we choose Map, Multiple threads call lock(), seems works if there no other variables in Data, otherwise we gonna make sure other variables are thread safe.
If we choose Record object ( Integer(RecNo)), I think it may be a chaos, because all the thread are accessing the Data object and calling any method at any time, the original client may not be able to unlock the record because by RMI we means two calls my not be handled by the same thread.
The wait() and notify() methods are used to coordinate processing between threads.
A print queue is a good example. To have something to print, the printer thread must
wait() for an output file to arrive in the queue. To protect an object, however, change
its state only when it is locked (synchronized code). Synchronized is used with wait()
and notify() to protect the shared "condition" flag.
For example, if there are 10 threads in Data "waiting room", the one we want to notify is A. when notify() is called, only one arbitrary thread is awaken, which one we don't know, suppose it is B. B is not the one want, but it waste the "notification" and locks Data and then goes back to Data "waiting room" after checking that the lock still there. That's it. Thread A is still waiting and the important notification is wasted.
If we use notifyAll(), all the threads in Data "waiting room" are awaken. so this time A get a chance to lock Data and find that the lock is gone, so successfully locks the record. B goes back to Data "waiting room" since the lock still there.
I'm just getting started on this, and I was thinking along similar lines - synchronising on the Data or Map object and using wait()/notifyAll(). But there's one thought nagging away at me...
Any attempt to lock a resource that is already locked should cause the current thread to give up the CPU, consuming no CPU cycles until the desired resource becomes available.
Strictly speaking, doesn't the approach above break this requirement? All waiting threads will wake up every time a record is unlocked. The ones that are waiting for a different record will go back to waiting, but will consume some cycles before doing this.
So I'm now thinking about locking on the record instead, which will make things a bit more complicated. Am I just being paranoid and overly picky?
My opinion is the "current thread" that trying to lock a resource which already been locked will have to give up the CPU (being blocked). This requirement does not mention anything about those waiting threads of the locked resource, in this case, it's the Data.
We have to give all waiting threads a chance to check if the unlocked record is what they are waiting for. The method notify() only arbitrarily picks up a waiting thread, this one may not be the one that want this just unlocked record.
Remember that notify() does not wake up "all" threads. Rather, obj.notify() wakes
up one thread that is waiting on 'obj' while obj.notifyAll() wakes up all the threads
that are waiting on 'obj'. Use notifyAll() when several threads are each waiting for
a condition within 'obj'. Those that don't see it can simply wait() again.
Yes, I've got that. The "problem" (if it is one) is that those threads that are woken up on the wrong condition have to check the condition before waiting again. Which wouldn't bother me at all if it wasn't for the precise wording of the requirement.
I suspect that it's not a problem. But I don't know...