Codes for this class is:suncertify.db
Class DataFactory
java.lang.Object
|
+--suncertify.db.DataFactory
--------------------------------------------------------------------------------
public class DataFactory
extends java.lang.Object
This singleton class provides access to Data objects. It * guarantees only one instance of Data per database file. *
Admittedly, i did miss out the conjunction "but". My sentence should read, "Q2. Phil mentioned that notify() should be deprecated, but in this thread, Peter said notify() has its place. But at the moment, analysis shows notifyAll is safer and notify() starves threads even for a single condition check."[Javini]:By the way, are you sure Phil said that notify() should be deprecated (admittedly your sentence is ambiguous as to which person "in this thread" refers to);
[Phil]:Though, reading Max, it looks like notify() should be deprecated, yet it isn't... (anyway not yet)
![]()
LOL, you are right about the inquisitive part.[Javini]:Keep in mind that it may take a while to understand threads, thought certainly you seem to know quite a lot and are very inquisitive
[Andrew]:If you only have a single condition to check then you are quite safe with just using notify(). But if multiple threads can go into wait() state on a single mutex waiting for different conditions, then you really need to notify all of them so that they can all check whether their personal condition has changed.
So if you had a mutex on recordOne then you know that there is only one condition for this mutex (recordOne is either locked or unlocked) and you could safely call notify() on a single thread waiting for recordOne.
.Here's the thing: Most operating systems use a combination of PE and TS, exactly for this sort of issue(Thread(Max) waking up again and again). That is, all other things being equal, the priority of the thread that's been waiting the longest gets bumped a bit, eventually culminating into a winning advantage, and starvation is avoided
Analysis below does show that T2 benefits from a future unlock:[Phil]:T1 owns L1
T2 waits for L1
T3 owns L2
T4 waits for L2
T1 unlocks and calls notify().
T4 is chosen and ... keeps waiting.
T3 unlocks and calls notify()
T4 is chosen again( why not) and is granted L2
T2 is still waiting... for ever? No, not sure, it may benefit of a future unlock, but it missed a chance to get L1 when it was released
In my assignment, the lockRecord API states:[Max]: That is, you're already requiring that a convention be followed(lock, modify, unlock), so what actual, real problem is being solved here?
It seems to me that the locking API only applies to update and delete. The lock/modify/unlock convention cannot apply to create because you do not have a recordNumber for lock(). So i have to make a decision on readRecord and createRecord. So i decided to make both thread-safe. I realize that in your book (great book by the way), the lock/XXX/unlock convention even applies to reads (getDVD() in DVDDbAdapter class)// Locks a record so that it can only be updated or deleted by this client.
// Returned value is a cookie that must be used when the record is unlocked,
// updated, or deleted. If the specified record is already locked by a different
// client, the current thread gives up the CPU and consumes no CPU cycles until
// the record is unlocked.
public long lockRecord(long recNo)
throws RecordNotFoundException;
No. The problem is that each time you write "(it does not matter)", in fact it *DOES*.
[Max]: What actual, existing, problem are you solving here?
What actual, existing, requirement are you implementing?
Q8 is still grey for me, but i can see a little light at the end of the tunnel. Let me see if i understood your following statements correctly:
[Andrew]: But if multiple threads can go into wait() state on a single mutex waiting for different conditions, then you really need to notify all of them so that they can all check whether their personal condition has changed.
So if you had a mutex on recordOne then you know that there is only one condition for this mutex (recordOne is either locked or unlocked) and you could safely call notify() on a single thread waiting for recordOne.
But if you had a mutex on a collection of records, then calling notify() on that collection will only transition one thread to blocked state (and then to runnable state), and when it transitions to runnable it may find that the condition it was waiting for (the individual record lock within the collection) is still not available - which will result in all the waiting threads returning to waiting state, even though there is potentially a lock free.
First, let me put a little meat into the codes:
code:
Suppose
1. Thread T12 runs lock(recNo) and successfully put recNo 12 into lockedRecords and exits lock method but has not started on unlock(recNo 12).
2. Since T12 exited, lockedRecords monitor is available. Suppose T35 runs lock(recNo), acquires lockedRecords monitor and successfully put recNo 35 into lockedRecords and exits lock method but has not started on unlock(recNo 35).
3. Now T1 and T2 would like to lock(recNo 12) and T3 and T5 would like to lock (recNo 35).
4. Threads T1, T2, T3, T5 successively got lockedRecords monitor but go to Waiting state because recNo 12 and 35 are still contained in lockedRecords.
5. T12 manages to get lockedRecords monitor and run unlock(recNo12) and does a lockedRecords.notifyAll()
Q1. In this case, all of threads T1, 2, 3, 5 will go to Blocked state and JVM will select one to Running state. Suppose T3 got selected, T3 wastes some CPU, and go back to Waiting state, BUT at the same time releases lockedRecords monitor. So JVM selects one from the Blocked state (T1, 2, and 5) but NOT T3 as it is in Waiting state. Is this understanding correct?
Q2. Now let's suppose lockedRecords.notify() is used instead of notifyAll. So JVM chooses one thread from (T1,2,3,5) from Waiting state to Blocked state. Let's consider the worst scenario: JVM chooses T3. T3 runs line 4, go back to Waiting state, BUT also releases the lockedRecords monitor. No other threads are in the Blocked state -> Thread starvation.
Nobody calls notify, so these threads cannot come out of the Waiting state. T35 will eventually invoke lockedRecords.notify() but in effect one out of T1,2,3,5 will get to call unlock(). The other 3 threads starve. Is this correct?
Follow-up post...:
Hey, wait a minute ... there may be no starvation even for notify()
Let's continue the analysis:
...JVM chooses T3. T3 runs line 4, go back to Waiting state, BUT also releases the lockedRecords monitor. No other threads are in the Blocked state.
But thread T35 to the rescue. T35 eventually runs unlock(recNo 35) and does a lockedRecords.notify().
1. Because T35 calls lockedRecords.notify(), JVM chooses one of (T1,2,3,5) from the Waiting state to Blocked state. (Remember now that recNo 12, and 35 are no longer in lockedRecords.)
2. Say JVM chooses T1 (it does not matter).
3. T1 goes to Running state because T35 releases the lockedRecords monitor when it exits unlock(recNo), and there is only one thread namely T1 in the Blocked state.
4. At this stage, T2,3,5 are in Waiting state.
5. T1 runs lock(), put recNo 12 into lockedRecords and finally, unlock() removing recNo 12 from lockedRecords and calls lockedRecords.notify(). (Now, again, recNo 12, and 35 are not in lockedRecords)
6. Because T1 calls lockedRecords.notify(), JVM chooses one of (T2,3,5) from the Waiting state to Block state.
7. Say JVM chooses T2 (it does not matter).
8. T2 goes to Running state because T1 releases the lockedRecords monitor when it exits unlock(recNo), and there is only one thread namely T2 in the Blocked state.
9. At this stage, T3,5 are in Waiting state.
10. T2 runs lock(), put recNo 12 into lockedRecords and finally, unlock() removing recNo 12 from lockedRecords and call lockedRecords.notify(). (Now, again, recNo 12, and 35 are not in lockedRecords)
11. Because T2 calls lockedRecords.notify(), JVM chooses one of (T3,5) from the Waiting state to Block state and so on ..., and hence the remaining threads 3 and 5 will also go to Running state.
Hence no thread starvation!
Is this correct?
Does the JComboboxes for Name and Location suffice in fulfilling this requirement?Your user interface should be designed with the expectation of future functionality enhancement.
[Phil]:But I *know* that he didn't call notifyAll() in lock() because he was the first guy here to point out the issue in Max's locking example.
I think you still get the 'win' here.