Originally posted by liqun chang:
1: From you reply,i guess if i remove notifyAll() from my lock method,i am ok.Am i right? About communicatin
between threads,i also don't think notifyAll() is necessary within lock method,only because Max's suggesting in anoter thread,because the article is long and there is a lot of discussion on it,i didn't finish reading.
Yes, I would recommend removing the notifyAll() from the lock method, because if you think about it, no thread really cares to be told when a record has been locked. Threads do care about being told when a record is no longer locked, because a thread may be waiting (in the lock method) for that record to become unlocked.
2: I am always thinking about Max'sugesting,if i use the only one mutex that either for record lock or file read/write lock,is the notifyAll() method that is located in lock method is necessary?
Could you give me some suggest?Same comment as for 1 above. I think you can safely remove the notifyAll from the lock method. When the end of the synchronized block of code is reached, all other threads that may be waiting for that synchronized block of code will be notified. That is sufficient, you do not need to also notify threads waiting for your locking variable, since adding a record to the locking variable can never help a thread waiting for a lock to become available. The unlock method, in which a record is removed from the locking variable, is of interest to any thread waiting in the lock method, and hence that is why the notifyAll is present in the unlock method.
In my design(as mention in the next section),I decide to use two mutexes
(WeakHashMap object and RandomAccessFile object).Am i right? or i use
FileChannel instead of RandomAccessFile.because i know FileChannel a little
,i hope to use it to get some experience.
I don't recommend the use of a FileChannel for this project as it appears to be explicitly prohibited by a document posted on the Sun site (you can see this discussed here: Topic: NIO prohibited for SCJD project?.
Please you give me reply,and George where did you come to?
Ok wait for your reply,and then i will go to read/write lock seciton.
Regards, George
SCJP, SCJD, SCWCD, SCBCD
Originally posted by liqun chang:
I will discussion
about thead safe.Hope you give me some comments.
Regards, George
SCJP, SCJD, SCWCD, SCBCD
I don't recommend the use of a FileChannel for this project as it appears to be explicitly prohibited by a document posted on the Sun site (you can see this discussed here:
Best Regards<br /> <br />SCJP1.4 SCJD1.4 SCEA
I have a concern about the pseudocode in the isValidated method, however. If I understand correctly, isValidated is called whenever lock is called (in other words, it's called more than one time). The pseudocode indicates that the header information is read from the database file and then all the records are read. This is a lot of work to do each time the isValidated method is called (which is each time the lock method is called). My suggestion is that the header information in the database file should be read only once (perhaps when the Data class is instantiated). The isValidated need only seek to the correct location for the recNo and read the validity flag to determine: 1) whether the record physically exists in the database file, and 2) whether the record has been marked for deletion or not.
public void isValidated(recNo) throws RecordNotFountException
{
//raf is another mutex
synchronized(raf)
{
raf.seek(position);
}
//read record that specified by recNo
//judge whether record is really existing in datafile,if not throw RecordNotFoundException,else go on
//judge whether record has deleted flag,if yes throw RecordNotFoundException,else go on
}
lock
{
isValidated(recNo);
synchronized(lockMap)
{
//some codes.
}
}
public void isValidated(recNo) throws RecordNotFoundException
{
RandomAccessFile raf;
raf=new RandomAccessFile(file);
synchronized(lockMap)
{
//while recNo in lockMap
lockMap.wait();
//else read record and judge recNo validity.
}
}
Regards, George
SCJP, SCJD, SCWCD, SCBCD
I think the DataSchema class is the way to go.
1. I think the correct thing to do is to put the seek, read, and write, all within the same block synchronized on raf. This is your answer c. The reason is this: you want the seek and read (or seek and write) to be atomic. In other words, you seek somewhere in the file and then you want to read at that location. But you want these two actions to occur as if they were a single action.
public void isValidated(recNo) throws RecordNotFoundException
{
//raf is new mutex
synchronized(raf)
{
raf.seek(position);
raf.read();
}
//judge whether recNo is really exist in datafile,if not throw RecordNotFoundExcption,if not go on
//judge whether recNo has deleted flag,if has throw RecordNotFoundException,else go on
}
3. I don't like the isValidated implementation here. I don't like opening the raf every time this method is called. Think about what happens when you get all the records from the database. First you call find which examines each record in the database (for which isValidated is called), so the raf is being opened once for each record in the database. Then when you get the array of recNos from find you call read for each record in the database (for which isValidated is called), so the raf is being opened once for each record in the database (again). So, for a find that gets all the record in the database, you are calling isValidated, (which is opening the raf) twice as many times as there are records in the database. I think this is definitely a worse implementation.
I'm not sure if I fully understand Max's point here ("the key is write and write conflict"). Should it be: "the key is read and write conflict?" I guess I agree, but it comes down to the situation. When I'm about to update a record I want to get it's latest values, and I'm willing to pay the price to lock(recNo), read(recNo), and unlock(recNo). When I'm just executing a user's search request, I'm willing to take my chances and just read what's there without doing the locking. Doesn't that mean that sometimes the user may be looking at something out-of-date (or even worse something partially written)? Yes, that's true, but it's not really harmful because if the user decides to book a stale record, as part of that booking operation, I will do an exclusive read (thereby picking up the latest values for that record).
You can create a Record class that will encapsulate the record data. Or you could just use String[]. It's up to you. You can also create DataInfo class as you say, or you might find that when you start implementing your table model that you can just handle the collection there as a member variable in the table model class. There's nothing wrong from an OO perspective with the classes you propose, it's just that you may decide as you get further involved in the implementation that you don't get a lot of additional benefit by making them their own class. This is something that will become more clear as you proceed.
i always don't know why you don't answer my questions
About atomic:If methoda and methodb be located in one method(or be called in one action),then we can say that we make methoda
and methodb atomic.Then methoda and methodb must run finished at the one time.
Am i right?
About the exclusive writting(for example:update,delete),i need to lock the special record and do writting operation,also
use the lock() and update() and unlock() in a single action.
(1): Whether you suggest me to use read() that there is not lock before it for concurrent reading? and let find to invoke read?
(2): Whether i need to worry about the concurrent reading at the same time there is exclusive writting?Because when i have read
some record and display them in JTable at the same time(or only after reading) some records has been changed.Is this conform
to Sun specification?
The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
Just having them in the same method will not make them atomic - the JVM scheduler can swap one thread out while it is in the
middle of a method. What you need (and what you seem to be doing) is to put the code inside a synchronized block.
You do not need to use the lock() and update() and unlock() within a single (atomic) action, nor do they necessarily all need to be in the same method (although most candidates appear to be doing this).
The lock() and unlock() method perform logical locking and unlocking of a record. You have to make portions of the update() method atomic, since you cannot allow a different thread to change an underlying object (e.g. the file pointer) before you get to do your write to file.
But there is no such problem with the lock(), update(), and unlock() operations - if the three method calls are not within an atomic block, it will not matter. No other thread can change the logical lock that was granted to you, so when your thread gets sliced in again, everything will still be in the same state.
Note that read() itself should have a synchronized block to ensure that it's file pointer does not get changed by another thread.
If you did decide to guard against this, you will have to consider what level of transaction isolation you want for your database operations, and this is definately getting beyond the requirements of the assignment.
The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
joke time: What is brown and sticky? ... ... ... A stick! Use it to beat this tiny ad!
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
|