Derek Canaan

Ranch Hand
+ Follow
since Nov 05, 2003
Merit badge: grant badges
For More
Cows and Likes
Cows
Total received
0
In last 30 days
0
Total given
0
Likes
Total received
0
Received in last 30 days
0
Total given
0
Given in last 30 days
0
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Derek Canaan

Hi Jay,
You're absolutely right
I'm using UltraEdit. When i copy and paste the entire file onto NotePad and saved it as the same filename, run javadoc again, the problem disappears.
Now i have to find out which UltraEdit settings to change so that i don't have to do the same thing (copy, paste, and re-saved) for the rest of the files.
I would have never figured this asterisk-problem out. Thanks Jay .. you're great.
rgds,
derek
[ February 20, 2004: Message edited by: Derek Canaan ]
Hi,
Problem:
-------
The DataFactory.html Javadoc generated includes asterisks intermixed in the comments as follows (note the asterisk between 'It' and 'guarantees; and at the end of the sentence:

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. *

Codes for this class is:
The javadoc command issued is:
Q. Why do the asterisks in the javadoc comments appears in the generated html file?
java version used is 1.4.1_02:

Any help is appreciated.
rgds,
derek
[ February 20, 2004: Message edited by: Derek Canaan ]
Hi Javini,

[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);

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."
But yes, Phil did suggest it:

[Phil]:Though, reading Max, it looks like notify() should be deprecated, yet it isn't... (anyway not yet)


[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

LOL, you are right about the inquisitive part.
My problem is i am having a tough time harmonizing what Andrew and Max said in the context of some possible designs for scjd:
In the context of scjd, Andrew basically gave two rules of thumb when to use notify and notifyAll:
1. Use notifyAll when mutex = collection of records
2. Use notify when mutex = a particular record
But i have drawn up two scenarios which seem to suggest:
1. It is ok to use notify even if mutex = collection of records
2. Using notify when mutex = a particular record may not be safe. It may cause thread starvation. Use notifyAll prevents that.
So my current state of understanding =
rgds,
derek
ps: thanks for the book recommendations. i see if i can get my hands on them
[ February 16, 2004: Message edited by: Derek Canaan ]
Hi Phil, Andrew, and Max
Let's put Andrew and Max statements and run a scenario in the context of a possible SCJD design:

[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.



Now in the light of what Max said below, notify() even under this single condition check is *not* safe:

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

.
1. T1, T2 competes for recNo 5.
2. T2 gets monitor.
3. T1 goes to wait pool
4. T2 finishes locks but has not started unlock
5. T3 wants recNo5, goes to wait pool
6. T2 unlocks, call notify()
7. T3 gets monitor
8. T1 continue to wait, OS bumps up T1 priority
9. T3 finishes locks but has not started unlock
10 T4 wants recNo5, goes to wait pool
11 T3 unlocks, call notify()
12 T4 gets monitor
13 T1 continue to wait, OS bumps up T1 priority
14 Repeat block and T1 waits forever ...
Because notify() nullifies OS priorities setting for waiting threads, T1 continue to starve. If notifyAll() is used, T1 gets to run.
Q1. Can we conclude that we should never use notify() even if there is only one condition for the mutex?
Q2. Phil mentioned that notify() should be deprecated, 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.
Comments?
derek
[ February 16, 2004: Message edited by: Derek Canaan ]
Hi Phil,
Thanks for bearing with this thread (pun not intended). The codes in question:

[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

Analysis below does show that T2 benefits from a future unlock:
T4 is chosen. T4 locks(L2) and T4 unlock(L2). At this point the lockRecords collection is empty! When T4 unlocks, lockRecords invokes notify(). Since T2 is the only thread in the wait pool, JVM has to choose it, and T2 runs lock and unlock L1.
Q1.If "it missed a chance to get L1 when it was released", does this constitute thread starvation?
Q2. When notifyAll() is used instead, T2 can also miss a chance to get L1 when it was released. Does this constitute a thread starvation? What is the official technical definition?
Q3. Could we conclude from the analysis, that for designs synchronizing on a record collection monitor and calling notify(), there still will not be any thread starvation?
Comments?
rgds,
derek
[ February 16, 2004: Message edited by: Derek Canaan ]
Hi Max,

[Max]: That is, you're already requiring that a convention be followed(lock, modify, unlock), so what actual, real problem is being solved here?

In my assignment, the lockRecord API states:

// 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;

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)
But, I suppose one can put in lock(-1) to make the convention applied even for create (for consistency).
BTW, i do believe you that no points will be penalized even if i didn't do it. It's defendable too.
rgds,
derek
[ February 16, 2004: Message edited by: Derek Canaan ]
Hi Phil,

No. The problem is that each time you write "(it does not matter)", in fact it *DOES*.


Please bear with me as i run this analysis over for notify() case:

If the analysis is run for all other cases, the end result is still the same. No threads will be starved regardless which thread is chosen after notify() because the thread who calls lock will finally unlock, and other threads will have a chance to run.
Please comment,
Derek
[ February 16, 2004: Message edited by: Derek Canaan ]
Hi Max and Phil,
Felt a bit bad for starting a war , but, may i join in?

[Max]: What actual, existing, problem are you solving here?
What actual, existing, requirement are you implementing?


First, i think defensive copying, implemented or not is defendable.
In a cached-design, it's defendable because it makes the data consistent, and the Data class thread-safe. It's the same reason why we implement createRecord() in a thread-safe manner even though we are not explicitly asked to (gui only updates and searches), so that when a client invokes Data.createRecord(), we will not get data inconsistency especially for design that re-uses deleted records.
Furthermore, this gives system consistency. We have a thread-safe readRecord() and a thread-safe createRecord(). Clients are not able to mess up my data when they invoke Data.readRecord() or Data.createRecord(). My assignment states that "marks are awarded for a clear and consistent approach.
Lastly, i want to be protecetd from an assessor who may say, "Hey, i can see a security hole here. The system's locking mechanism is breached." Hence, i choose to err on the safer side.
rgds,
derek
Hi Phil,
I was trying to understand what Andrew was stating on mutex on recordOne vs. mutex on collection of records by using some codes. Would you comment on this analysis:

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?

Hi Max,
First, thanks for your contributions in this forum. They helped me a lot. Please help me out here as i am trying to get a grip on this issue.
In the printing scenario, let's consider time-sliced vs pre-emptive OS.
Case A (time-sliced OS)
-----------------------
For time-sliced OS, notify() would not cause thread starvation because Thread(Andrew) will also be given a chance to execute. In this case, notify() or notifyAll() works. Probably, here notify() is more efficient, as only one thread is woken up. Is this right?
Case B (pre-emptive + notify)
-----------------------------
Let's consider pre-emptive OS. Thread(Andrew) may have the highest priority, but notify() nullifies all priorities. It "bypasses any and all priority that the various threads". So Thread(Andrew) will starve if Thread(Max) keeps waking up(and winning) again.
Case C (pre-emptive + notifyAll)
--------------------------------
Now let's consider notifyAll(). All threads will be waken up, but Thread(Andrew) keeps winning because he has the highest priority. So Thread(Max) starves. Is this correct?
Case D (equal priority threads)
-------------------------------
Now let's consider the scenario where the developer never use Thread.setPriority() in his codes. So all threads will have the same priorities because they inherit from the same main thread when they were spawned.
i. If OS = time-sliced, back to Case A. All threads get to run.
ii. If OS = pre-emptive, and notify() is used, Case B can happen if Thread(Max) keeps waking up(and winning) again.
iii. If OS = pre-emptive, and notifyAll() is used, Case B can also happen if Thread(Max) keeps being selected to run. Because for notifyAll(), only one thread is selected arbitrarily as far as the developer is concerned to run.
So ceteris paribus, notify and notifyAll have the same net effect.
Please advise,
Derek
Hi Phil,
While you're online, would you mind taking a look at Question 8 of this thisthread. It is with regards to my analysis to notify vs notifyAll based on Andrew's comments. I'm still struggling with the issue.
thanks,
derek
Hi,
My B&S assignment states under The User Interface section:

Your user interface should be designed with the expectation of future functionality enhancement.

Does the JComboboxes for Name and Location suffice in fulfilling this requirement?
Any advice?
rgds,
derek
Hi Jacques and George,
Just as you do, I like the shorter version too. It's also less clouded. And I like Jacques' reasoning too
Thanks guys,
Derek
Hi Phil,

[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.


Yes, that is my understanding too that he did not issue a notifyAll in lock(), but my 'guesswork' from his posts showed that he did use notifyAll in unlock() as he synch at database level and not at record level.
The post that Max conceded on notifyAll in lock() is found in this thread and i quote Max:

I think you still get the 'win' here.


Defensive copying is brought out by Vlad and Jim, in which the Data class'
readRecord method returns to the client a copy of the record instead of the
actual record reference itself. The danger of returning the actual reference is the client may do something with it that changes the states of the record reference without the proper locking protection. For example:This effectively also changes the name field of record 5 in the database cache.
In this scenario, the system's locking mechanism is breached.
rgds,
derek
[ February 10, 2004: Message edited by: Derek Canaan ]
Hi everyone,
Need your opinion on this:
Which is more preferred and why?
thanks,
derek