aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes how can you avoid nested synchronization Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "how can you avoid nested synchronization" Watch "how can you avoid nested synchronization" New topic
Author

how can you avoid nested synchronization

Wayne John
Greenhorn

Joined: Nov 10, 2005
Posts: 7
in lock() method we need to check records validity, make sure the record is not deleted before locking it.
I found I can't avoid to use nested synchronization, please read following code , how did you implement your lock method? can you avoid nested synchronization? thanks.
Andrew Monkhouse
author and jackaroo
Marshal Commander

Joined: Mar 28, 2003
Posts: 11481
    
  94

Hi Wayne,

While you should always try to avoid nested synchronization, sometimes it is not possible to avoid it totally. As long as you always nest in the same order you should be OK.

But some alternatives for you: You could have a local collection containing the list of deleted records which can only be modified while you own the mutex on lockmap. So you could then just check the deleted record in that collection without ever going to the RAF (although this requires you to read the entire RAF at some point).

Alternatively, within your lock method you could add the lock details to the lockmap and release your mutex on it. Then go and check the validity of the record and, if it is not valid, silently unlock the record.

Regards, Andrew


The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
Wayne John
Greenhorn

Joined: Nov 10, 2005
Posts: 7
But some alternatives for you: You could have a local collection containing
the list of deleted records which can only be modified while you own the mutex on lockmap.
So you could then just check the deleted record in that collection without ever going to the RAF



Hello Andrew :
thank you for your reply.

acutally I had the same idea before, it's similar with your comments.
but, I don't think I can use lockmap as mutex .I write down the code below,
could you read it and give me some suggestion, I'll really appreciate for it!



[ December 14, 2005: Message edited by: Wayne John ]
Mihai Radulescu
Ranch Hand

Joined: Sep 18, 2003
Posts: 916

Hi, John


If you choose to combine the lock mechanism with the IO feature you can land easly to the nested block probelm. This is not so nice but if you know the nest order you can avoid a deadlock.
You can also use the same look for both, but this can be a little bit to much.

An othre way to avoid this is to separate the lock mechanism from the IO features - two seperate classes. In this case you can synchronize separate all the read/write operations.

One more remarc to your last statement

thread could slice out from here, so this record could be deleted by other thread then this thread read a deleted record!


IMHO this is not a real problem. You can see it like this, even if your whole method will be atomic and it always retun the right records is still not enought, after you exit them metohd and you try to use the result (let's say to display it) an other thread can perform a delete. The read provides only a "view" from a specific moment(time), in the next moment the system may change.


Regards,
Mihai.
[ December 16, 2005: Message edited by: Mihai Radulescu ]

SCJP, SCJD, SCWCD, OCPJBCD
Wayne John
Greenhorn

Joined: Nov 10, 2005
Posts: 7
hello Mihai:
thank you for the reply.
maybe I wrote too much in my last post, could you read my following post and give me an answer . thank you.

void deleteRecord(int recno) throws Exception{
synchronize(raf){
try{ ......... delete a record from dbfile
} catch(IOException){
throws Exception
}
}............. //even this record was deleted from dbfile ,but thread could slice out in here, //and another thread could read this record which has already been deleted. // is this a big problem???

addDeletedRecords(recno);//this function will add one deleted record to arraylist.

}


in read() method, we also need to check record validity,
void read( recno) throws Exception{
//check if record has been deleted;
if(isDeletedRecord()){ throw Exception; }
...........> thread could slice out from here, so this record could be deleted by other thread then this thread read a deleted record! is this a matter? it's not dirty read, just stale read ,seems many people just ignore this problem. or we also need to put isDeletedRecord() into synchronize(raf) block?

synchronize(raf){ doing read process }

}
Mihai Radulescu
Ranch Hand

Joined: Sep 18, 2003
Posts: 916

Hi,

I don't realy understand your question.Can you be a little bit more specific.

Here is what I understant.

Your code snipplets are from your IO layer, by io layer I mean the class for read/search/write ?
If the answer is yes why you don't synchronize with same lock(on instance by example) all the IO methods? In this way delete and create are atomic, this can spare you from a lot of problems(one is nested synchronized blocks).

About the read probelm I already explain in my last post("One more remarc to your last statement ........" ).

I hope this hepl.

Regards,
Mihai
[ December 16, 2005: Message edited by: Mihai Radulescu ]
Wayne John
Greenhorn

Joined: Nov 10, 2005
Posts: 7
Hello Mihai:
thank you for the reply.
yes,the code snipplets is from IO layer. acutally I write one class called "DBFileAccess" for io processing, the Data class need to call this class to finish read , delete ,update operation.

if I put them into same synchronized block,
that means when I write function isDeletedRcord(), I have to use synchronize(raf){}block again . like this:
public void isDeletedRecord(int recno){
synchronize(raf){
return arraylist.contain(new Integer(recno));

}

}
I think it's low performance , because in data class , all read , update method need to call this method . and in lock() method I also need to call this method, so, the lock method will block file io operation.

if I use arraylist as mutex, when I call isDeletedRecord() method it won't block IO operation. I got confused about this.
Maybe I should listen your suggestion, make the things simple.
Alex Sharkoff
Ranch Hand

Joined: Apr 11, 2004
Posts: 209
Andrew said

While you should always try to avoid nested synchronization, sometimes it is not possible to avoid it totally. As long as you always nest in the same order you should be OK.


I guess we need 1) to determine what objects need to be accessed in a multi-thread safe fashion; 2) and then determine how it can be achieved.
That is what I've got so far:

1. For the logical locking (ie record locking) there is a static lockedRecords map that stores key/value pairs where the key is a record number and a value is a client who has locked it

2. For the physical locking (ie file locking) there is a static dbFile object that provides read/write access to the database file (it delegates read/write tasks to the instance of RAF)

3. For the record cache there is static recValidFlags list in which an element position represents a record number and the actual element is a record validity flag (of byte type, either Data.VALID_RECORD or Data. DELETED_RECORD). The actual number of elements in this list represents a total number of records in the file (both deleted and valid).
recValidFlags is initially populated on the start up (when the database file is chosen by the user) and is then maintained by the Data instances.
Collections.synchronizedList(new ArrayList<Byte>()) method is used to create a List instance used for this cache, which makes access to recValidFlags methods multi-thread safe.
The recValidFlags cache is used for a) checking whether the record exist; b) determining in what position to create a new record.
The recValidFlags cache is modified when a) a new record is created ; b) when a record is deleted

Data instances will synchronize on these three static objects ( ie lockedRecords / dbFile / recValidFlags ) in the following manner:

Data#read(int recNo)



Data#create(String[] record)



Data#lock(int recNo)



Data#delete(int recNo)


All comments are welcome.


[ December 19, 2005: Message edited by: Alex Sharkoff ]

Alex (SCJP 1.4, SCBCD 1.3, SCWCD 1.4, SCJD 1.4)
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
 
subject: how can you avoid nested synchronization