aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes not sure which methods must be synchronized Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Soft Skills this week in the Jobs Discussion forum!
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "not sure which methods must be synchronized" Watch "not sure which methods must be synchronized" New topic
Author

not sure which methods must be synchronized

joel smither
Ranch Hand

Joined: Jan 01, 2005
Posts: 31
Hi I'm working the UrlyBird developer project. I have implemented a seperate LockManager class to to the real work of locking and unlocking records. I have made these methods synchronized, because they need mutual exclusive access to some hashmaps I'm using to maintain information on which records are locked.

Is there really a need for nay other methods to be synchronized? In my Data class I have methods readRecord, updateRecord, findByCriteria, etc. These methods don't have to be synchronized do they?
Daniel Simpson
Ranch Hand

Joined: Sep 02, 2004
Posts: 181
Originally posted by joel smither:
Hi I'm working the UrlyBird developer project. I have implemented a seperate LockManager class to to the real work of locking and unlocking records. I have made these methods synchronized, because they need mutual exclusive access to some hashmaps I'm using to maintain information on which records are locked.

Is there really a need for any other methods to be synchronized? In my Data class I have methods readRecord, updateRecord, findByCriteria, etc. These methods don't have to be synchronized do they?


If your Data class is a Facade and the LockManager does the actual implementation, there is no need for your Data class methods to be synchronized for lock and unlock. All synchronization should be done in your LockManager. In my LockManager (similar to yours), I sychronized my methods lock and unlock. I also had a DataManager class that actually did the reading and writing to the database. In there, I synchronized my methods update and delete. I don't believe your allowed to synchronize read or create. There would be no point in synchronizing read, but you have to come up with a solution so the create method doesn't compromise thread-safety. Hope that helps!


SCJP 1.4<br />SCJD 1.4
joel smither
Ranch Hand

Joined: Jan 01, 2005
Posts: 31
I'm sort of weak on terminology. I believe my Data class is a facade...it is the class that implements the methods readRecord, createRecord, deleteRecord, updateRecord, lockRecord and unlock, etc. The lockRecord and unlock methods are not synchronized in this class. So is this what u mean by facade?

My LockManager sychronizes its methods called lock and unlock. When I want to update a record, I first call the lock method in my LockManager class. Once I get the lock I then call updateRecord to actually update the record.
Why do the updateRecord and deleteRecord methods have to be synchronized in my Data class?
Daniel Simpson
Ranch Hand

Joined: Sep 02, 2004
Posts: 181
Originally posted by joel smither:
I'm sort of weak on terminology. I believe my Data class is a facade...it is the class that implements the methods readRecord, createRecord, deleteRecord, updateRecord, lockRecord and unlock, etc. The lockRecord and unlock methods are not synchronized in this class. So is this what u mean by facade?

My LockManager sychronizes its methods called lock and unlock. When I want to update a record, I first call the lock method in my LockManager class. Once I get the lock I then call updateRecord to actually update the record.
Why do the updateRecord and deleteRecord methods have to be synchronized in my Data class?

Basically a Facade HAS another object which it uses to perform a task so in your case, it may look something like this:


So instead of your Data class doing the work, you have a LockManager in your Data class that Data uses to perform the task. If you are having LockManager do the locking and unlocking, you might want to consider creating another class that does all of the reading and writing instead of Data doing it directly. Then it would be a Facade. Just an idea. Also, you need to synchronized your update and delete. What if Thread-A enters update and starts updating the values for record 5, and then Thread-B cuts in and deletes record 5, then Thread-A cuts back in and tries updating the values for a record that no longer exists. That is only one of many scenarios. Hope that helps!
joel smither
Ranch Hand

Joined: Jan 01, 2005
Posts: 31
In the UrlyBird project there is no requirement for the end user to do a delete, as a result I've assummed this is an off-line operation that doesn't need to be synchronized.

Whenever I want to book a record (i.e. update the record) I perform a lock on it....it's the lock method in my LockManager class that is synchronized...so I still don;t understand why the update method needs to be synchronized. You have to have a lock on the record before you can update it.
peter wooster
Ranch Hand

Joined: Jun 13, 2004
Posts: 1033
Originally posted by joel smither:
In the UrlyBird project there is no requirement for the end user to do a delete, as a result I've assummed this is an off-line operation that doesn't need to be synchronized.

Whenever I want to book a record (i.e. update the record) I perform a lock on it....it's the lock method in my LockManager class that is synchronized...so I still don;t understand why the update method needs to be synchronized. You have to have a lock on the record before you can update it.


There are two areas that must be considered for synchronization.

1) the code that does logical resource locking, this code is used to get a token that prevents 2 clients from updating the same record concurrently. This interlock has no effect of low level I/O.

2) synchronization of access to the record cache or RandomAccessFile. This is needed to prevent one low level I/O operation from interfering with another. Eg. if you are using a RandomAccessFile the following could happen on read:
thread 1 seeks to record 10
thread 2 seeks to record 5
thread 1 reads data that should be coming form record 10, but gets data from record 5
all kinds of unpleasant errors.

This just gets worse if updates are involved, and caching doesn't help much since you will need to refresh or update your cache.
Charles Fung
Greenhorn

Joined: Jan 05, 2005
Posts: 13
so I still don;t understand why the update method needs to be synchronized.

To decide if a method should be synchronized, I would question:
1. would there be multiple threads in the VM? => YES for this client server application, every client request spawns a thread.
2. would this method access shared resource? If yes, would there be adverse effect when this and other methods access the resource?

In this assignment, the very basic shared resource is the data file. There should always be only one thread accessing it. Depending on the design, you might also need to protect cached records in memory and their lock status.

There are two criteria if update() does not need be synchronized:
1. The update method changes the data file using another object and that object protects the data file properly. If not, update() HAS to be synchronized.
2. The update() and read() methods do not have conflict. We know that update() touches only one field, so the change is atomic - either the field is changed or not changed. Otherwise, if update() touches more than one field, read() may read a record that is partially changed and that is not good.
IMHO, given update() accepts a String[] parameter, I would tend to make it generic (assuming changes to multiple fields) and synchronize it.


SCJD 1.4<br />SCWCD
joel smither
Ranch Hand

Joined: Jan 01, 2005
Posts: 31
I think I understand what you're saying, however I still don't think I need to make any method synchronized except for lockRecord and unlock methods defined in my LockManager class.

My Data class is used in local mode as well as remote mode to manipulate the records in the database. My Data class has an instance variable that is an instance of the LockManager class. When my GUI client needs to update a record, the first thing I do is lock the record (this is a synchronized method). Once the record is locked, I can update it, there is no need for this method to be synchronized is there? I then go ahead and update the record, then call the lock method (another synchronized method). Is this OK?
peter wooster
Ranch Hand

Joined: Jun 13, 2004
Posts: 1033
Originally posted by joel smither:
I think I understand what you're saying, however I still don't think I need to make any method synchronized except for lockRecord and unlock methods defined in my LockManager class.


Please reread my previous response, you do need to synchronize access to the RandomAccessFile or the Collection that contains your cache. This has nothing to do with the logical resource locking that your LockManager is responsible for. There is a race condition between two threads doing read from a RandomAccessFile and read and update must be synchronized if you are accessing a Collection.
joel smither
Ranch Hand

Joined: Jan 01, 2005
Posts: 31
Boy, the information provided on this thread is extemely enlightening, thanks for all who responded.

I want to make sure my locking is done correctly, so please forgive me if I appear to be rehashing some things...

I'm using RMI for networking. I have a Data class that implements readRecord, updateRecord, createRecord etc. Note that none of these methods are synchronized. The Data class implements my data layer so to speak. My Data class also has a LockManager. This class provides two methods, lockRecord and unlock ( which are synchronized methods).

In my client GUI, when the user wants to book a record (i.e. book a room) I first call my Data class (it has a lockRecord and unlock method as well). The lockRecord method in my Data class calls the LockManager method lockRecord to actually lock the record. Since my LockManager's lockRecord method is synchronized, only 1 client at a time can lock a record. Once I have the lock I call the updateRecord method in my Data class to update the record. Then I call my LockManager's unlock method to unlock the record. Doesn't this sequence of events ensure mutual exclusive access to that record? There's no way that 2 clients could update the same record with this scheme is there?

My second question is this: on a previous reply it was mentioned that I need to ensure access to my RandomAccessFile properly. In other words, one client could seek to record 5 while another could seek to record 10....all hell could break loose then...one client actually gets record 10 expecting record 5...

When I implemented the methods in my Data class, my filePointer variable is initialized once at start up (when I first open the file I read all the records in it and set the file pointer) and never modified again. From that point on the file pointer is just used as an offset to the appropriate record. So I'm thinking that my methods to fetch records are essentially thread safe. Is this correct or am I all screwed up here?


Also, Sun has instruction that state that I can;t change the DBAccess interface that the Data class implements, doesn;t this mean I can't add the synchronized keyword to those methods?
Charles Fung
Greenhorn

Joined: Jan 05, 2005
Posts: 13
joel smither: There's no way that 2 clients could update the same record with this scheme is there?

I think you are right. However, other clients can read concurrently.

When I implemented the methods in my Data class, my filePointer variable is initialized once at start up (when I first open the file I read all the records in it and set the file pointer) and never modified again.

This is not true. Refer the documentation on RandomAccessFile. The underlying variable filePointer changes when you read, write or seek(). RandomAccessFile methods are not synchronized so they are not thread-safe.

doesn;t this mean I can't add the synchronized keyword to those methods?

Synchronized is implementation-related, it does not appear in interface. Rather, it is used in class, so you are free to add synchronized to the methods.
peter wooster
Ranch Hand

Joined: Jun 13, 2004
Posts: 1033
Originally posted by joel smither:
Boy, the information provided on this thread is extemely enlightening, thanks for all who responded.

You're welcome.


When I implemented the methods in my Data class, my filePointer variable is initialized once at start up (when I first open the file I read all the records in it and set the file pointer) and never modified again. From that point on the file pointer is just used as an offset to the appropriate record. So I'm thinking that my methods to fetch records are essentially thread safe. Is this correct or am I all screwed up here?


You are caching all the records in a collection of some sort. If you modify that collection, you will need to ensure that the accesses to it are synchronized, especially if you implement create.


Also, Sun has instruction that state that I can;t change the DBAccess interface that the Data class implements, doesn;t this mean I can't add the synchronized keyword to those methods?[/QB]



You can't synchronize methods in any interface, but you can synchronize the methods that implement the interface in a class.
joel smither
Ranch Hand

Joined: Jan 01, 2005
Posts: 31
I'm not sure if I have my queston answered or not...I'm using RMI....

Let's suppose my server has done the following:

Registry myRegistry = LocateRegistry.createRegistry
(Integer.parseInt(port));
RemoteUrlyBirdDBAccess dbServer = new DataAdapterImpl(dbpath);
String serverObjName = "//:" + port + "/" +
RMI_SERVICE_NAME;
Naming.rebind(serverObjName, dbServer);

My server binds a dbServer object to the registry. This dbServer object has a connection to the database file...it has opened the RandomAccessFile containing the database records. More specifically, the DataAdapterImpl object has an instance variable of type Data. This Data object opens the RandomAccess File and provides the readRecord, createRecord, updateRecord, etc. methods for data access.

My clients gets a remote connection from the DatabaseFactory class. The DatabaseFactory does the folloiwng:

RemoteUrlyBirdDBAccess remote =
(RemoteUrlyBirdDBAccess) Naming.lookup(lookupString);

// Transform the remote interface
DataProxy proxy = new DataProxy(remote);
return proxy;

In other words, each client gets a unique proxy instance that contains the remote service object registered by the server. So I believe that each client is getting their own proxy instance which has effectively wrapped the remote service object. So each client is using the SAME Data object correct?

Now...in terms of threading I need to prevent concurrent updates: My Data class has a LockManager object that has a synchronized lockRecord method that locks a record. Once this is done I can update the record, then I can call my LockManager unlock method (also synchronized)to unlock the record.
This should take care of simulataneous updates right?

I don't want to prevent concurrent reads do I? It seems to me that several clients should be able to read concurrently, but since I'm using a RandomAccessFile and manipulating the file pointer...I need to make sure the manipulation of the file pointer is synchronized...what do poeple do here...do the synchronize every method in the Data class, use a synchronized block for the file pointer? Not sure what to do....
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: not sure which methods must be synchronized