I think NotifyAll() is required in lock() method. I have seen some discussions aound this topic. I thought of creating a separate thread just to understand this more. [I] Data.java[I]
IMO If you don't have notifyAll() method, then it is a database level locking implementation and not record level. Anytime a client need to book,update or delete a reacord, the client needs to acquire a lock on a specific record. After a lock is acquired on a specific record, why the client need to hold the entire lockedRecords object until it finishes the book,update or delete and then unlocks. Another client interested on locking a different record can have a chance to do so, if you notofyAll() immediately after you have acquired a lock on a specific record. Now question about whether another client can unlock a record originally locked by a client doesn't arise, if you have implemened the cookie correctly.
Hi Sud, we had a long discussion concerning the notifyAll()-call in the lock()-method in this thread When I understand Max rightly it would be defendable if we would have a special implementation where a waiting thread could give up the waiting status. But because I haven't such an implementation and I suppose you also not, then I would omit the notifyAll(). Regards Ulrich
Suds, it's possible you're confusing acquiring and releasing a sync lock with lock()ing and unlock()ing a record. If one thread is trying to lock() a record which is already lock()ed by another thread, it's got to wait(). During this time, it really doesn't matter if other threads manage to lock() that record, or any other records. We only care if another thread manages to unlock() a record, because that might be the record we're interested in. In Max's code, notifyAll() after a lock() makes sense only if there are two different types of lock() (DB-level and record-level) and one type can override another. E.g. if thread A is waiting for a record-level lock() and thread B succeeds in getting a DB-level lock(), thread A may need to be notified to stop waiting for one record, since the whole DB is now locked. Or not, depending on your design. But in general, there's no use for notifyAll() inside lock(). The other htreads are really just interested in knowing if unlock() as been accomplished, not lock().
"I'm not back." - Bill Harding, Twister
Joined: Sep 23, 2003
Hi Jim, Thank you for your reply. I think I am missing some imp stuff here. In line 4, the synchronized locks lockedRecords. Means only one thead can acquire a lock of lockedRecords object and enter into the synchronized block. Other threads have to wait until the lock is released from the original thread (or timeout). Lets take an example. There are 2 Threads (A and B). Thread A needs to delete record #23 and Thread B needs to update record #24. Thread A reaches line 4 and acquires a lock for lockedRecord object. Thread A modifies lockedRecords in line 16. Note that Thread B is still waiting at line 4. Now what is the need to keep Thread B waiting further. Thread B can also enter the synchronized block, if Thread A executes NotifyAll() in line 17. Without NotifyAll() method, Thread B has to wait until Thread A completes its delete() operation and then executes unlock().
[ November 14, 2003: Message edited by: Suds Pati ]
Joined: Jan 30, 2000
Lets take an example. There are 2 Threads (A and B). Thread A needs to delete record #23 and Thread B needs to update record #24. Thread A reaches line 4 and acquires a lock for lockedRecord object. Thread A modifies lockedRecords in line 16. Note that Thread B is still waiting at line 4. Now what is the need to keep Thread B waiting further. Thread B can also enter the synchronized block, if Thread A executes NotifyAll() in line 17. Without NotifyAll() method, Thread B has to wait until Thread A completes its delete() operation and then executes unlock() No, without notifyAll(), thread B just has to wait until thread A passes line 18. By exiting the sync block, thread A releases its sync lock on the lockedRecords monitor. That's enough to allow thread B to proceed and acquire a sync lock on lockedRecords, and proceed with the rest of the methods. The thing to realize is, thread B was never executing wait(), therefore it doesn't need any notify() or notifyAll(). Thread B was just attempting to acquire a sync lock on a monitor. Once that monitor becomes available, thread B can acquire it, without any notification. When thread B gets to line 6, record 24 is not in the map of locked records, so the while condition is false, and thread B does not wait(). The only reason a thread would need to wait() is if another thread has locked the same record. If that happens, you want to wait until the record is unlocked. Being notified that a lock() is complete is useless; the while loop will just eveluate to true again, and wait() will be repeated. [ November 14, 2003: Message edited by: Jim Yingst ]
It all of course depends on your design. I started out with a quite complex locking mechanism, where I had inserted wait()s at 3 different positions and the same number of notifyAll()s. (This got so complex that I eventually abandoned the whole design).
In the straightforward solution, there is only a wait() in the lock() method, for when a thread wants to lock a record that is still locked by a different thread. Then you will only need one notifyAll() (or perhaps even just notify(); think this through!) in the unlock() method.
In general, as soon as you insert a wait() somewhere, you should ask yourself under what conditions you want the thread to wake up again. Then add a notify(All) for that situation. Then spend some extra time pondering if the notify is guaranteed to be executed in the future...
SCJP 1.4, SCJD
Joined: Dec 29, 2004
Your post started me thinking about notify and notifyAll, which eventually led me to discover a painful flaw in my own code. You may want to read about it in this thread.