aspose file tools*
The moose likes Developer Certification (SCJD/OCMJD) and the fly likes Lock/Unlock Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Developer Certification (SCJD/OCMJD)
Bookmark "Lock/Unlock" Watch "Lock/Unlock" New topic
Author

Lock/Unlock

Ricardo Polero
Ranch Hand

Joined: May 18, 2001
Posts: 128
Hi, I have a doult
I am using a HashMap to hold my record locks.
private Map lockTable = Collections.synchronizedMap(new HashMap()); So my locks and unlock methods looks like will be only
the put and release the reg in the collection. But I don't sure what kind of code will; be in Data class. I a normal project this approach will be enought but i'm not sure for this.
Some ideas ?
Ricardo Polero
Ranch Hand

Joined: May 18, 2001
Posts: 128
C'mon guys !
Some ideias ?
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Well, if you search through this forum you'll find plenty of locking discussion =8^)
And you're not really clear about your approach. For instance, this Map, it maps what to what? Does it map record numbers to something identifying the client that owns the lock? Do you implement your locking code in the Data class, and if so, how do you identify the client? Without more information it's hard to give you feedback. Nevertheless, two remarks.
First, reconsider your use of a synchronized collection. Specifically, write down in detail how the processes of locking a record and unlocking a record are supposed to work, then ask yourself how both algorithms need to be synchronized. From this will follow whether a synchronized collection actually buys you anything.
Second, reconsider your decision - if indeed that's what you do - to implement the locking code in the Data class. Concentrate on class responsibilities, keeping in mind that in an ideal object model each class has a single, narrow, focused responsibility. I would contend that the responsibility of the Data class is to implement a single, local, file-based database table. If you accept that, it follows that the locking implementations provided by Sun are fine as-is (it's all the locking you need for a local table), and also the much-abused Singleton pattern is probably inappropriate when applied to Data (how often have you used a database with exactly one table)?
- Peter

[This message has been edited by Peter den Haan (edited September 13, 2001).]
Ricardo Polero
Ranch Hand

Joined: May 18, 2001
Posts: 128
Hi Peter!
I used the sync map to store the instance of client impl (retrieve when lookup the server) and the reg ID. If for one client (like Maria) has null in value it's means she is logged but she did't lock any reg. etc.
I'm my approach lock will be only a put in the Map and unlock will be put null in maria's value position.
So looks like to me so easy and works fine and fast. But I'm not sure it this approach will be accepted or if not elegant, accepted etc. I have Forte/C++ background an I used this patterns many times
Would you help me please
Emily Bache
Greenhorn

Joined: Sep 13, 2001
Posts: 1
Hi,
I'm also working on the database locking. The approach I've chosen is to change the method signatures so that lock() returns a integer key, and the unlock() method takes that key as an argument, so that the lock is only removed if the correct key is given. That means that only the client that made the lock on a record can unlock it.
What I'm wondering now is whether it would be a good idea to add the integer key to the method signatures of the methods that modify the database - ie modify(), add() and delete(). Then these methods could check whether the client has a suitable lock before they are allowed to make the modification. This might make my data server more robust by preventing future developers writing client code which calls modify() without first calling lock().
However, it makes things more confusing in local mode. Since locking is not needed in local mode, the local implementation of my Data interface will just ignore this key, and only the networked data server will actually use it. I'm not sure it's worth the hassle since the client I write will always call lock() before modify().
Any thoughts welcome,
Emily
Ricardo Polero
Ranch Hand

Joined: May 18, 2001
Posts: 128
Hi
Really I'll use adapter patterns in client side so I'll call the local version of the data method and RMI ones (in my case) for remote.
My problems is in this approach the lock/unlock will be only one line of code (just put/remove for Map ) in Data class and this seem to me soo easy , I want more opinions thats all, it's ia allowed the approach of lock/unlock not Data class based
All opinions are welcome !
Ricardo
Ricardo Polero
Ranch Hand

Joined: May 18, 2001
Posts: 128
HI, again
PLS I want to know if someone implemented the lock/unlock just with HashMap operation
THX
Pieter Kuijpers
Greenhorn

Joined: Sep 26, 2001
Posts: 2
Hi,
I implemented the locks with a HashTable using the record number as key and the thread name (Thread.currentInstance().getName() ) as value. When locking, I check the record is not currently locked by another thread. When modifying the database (add, modify, delete), I check that the current thread has locked the record that is to be modified.
This works fine when multiple threads are using the Data object in a single JVM, but I'm running into trouble now I've exported the Data object using RMI to multiple (remote) clients. It appears that the mapping of clients to threads in the server JVM is not fixed: repeated calls from a single client can be executed in different threads on the server. For example:

  • client calls server.lock(1) => executed in thread "RMI TCP Connection(1)" on the server.
  • same client call server.unlock(1) => executed in thread "RMI TCP Connection(2) on the server. This fails, because the server thinks a client is unlocking a record that is locked by someone else.

  • So, using the thread name is not a reliable way to identify a connection when using RMI. I'm now trying to think of something else, maybe the token approach I read in another post (having the lock method return a token that can be used to modify and unlock).
    [This message has been edited by Pieter Kuijpers (edited September 26, 2001).]
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
A particularly elegant solution is to give each client its own Connection remote object that implements the DataInterface. This solves all your problems in one go without unnecessarily burdening the client code with tokens, additional arguments or whatever. After all, the Connection on which the method (lock, unlock, add,...) is invoked is the client identity you're looking for.
No need to change the Data method signatures. No need to burden Data with multi-user related code (e.g. locking code). No need to burden clients with identification tokens. Sheer programming bliss and unsurprisingly the way every commercial database works.
Another bonus is that three lines of code implementing java.rmi.server.Unreferenced gives you automatic clean-up of dead clients' locks.
- Peter

[This message has been edited by Peter den Haan (edited September 27, 2001).]
Jack Zhang
Greenhorn

Joined: Sep 06, 2001
Posts: 5
Peter,
Is my understanding of the relationships between the Server object, Connection object and the Data object correct?
1, the Server is a connection factory, with the Data object as it's member variable (to keep it unique and pass its reference to all client connections)
2, the Connection object serves a single client, while accessing the shared Data object.
Thanks!
Jack
Jack
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Jack,
Variations on the basic theme are possible, but yes, that is a fine interpretation of the general pattern. When combined with RMI, this implementation is also a treasure trove of GoF patterns that will help make your documentation buzzword compatible.
- Peter
Mark Spritzler
ranger
Sheriff

Joined: Feb 05, 2001
Posts: 17249
    
    6

Ok, here is my dilemna. what is holding me up. Do you pass the Connection Object to the client via a getConnection() method in the Server, and doesn't the Connection have a reference to the data, which makes the data have to be Serializable as well as the Connection Object?
If not, how do you get the Connection Object to stay on the Remote machine, and know which client it is working for
Thanks
Mark


Perfect World Programming, LLC - Two Laptop Bag - Tube Organizer
How to Ask Questions the Smart Way FAQ
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Mark,
Connection is a full fledged remote object in its own right (i.e. instanceof Remote and a subclass of UnicastRemoteObject) and does not need to be serializable, nor does any of the objects it holds references to. It lives on the server.
- Peter

[This message has been edited by Peter den Haan (edited September 27, 2001).]
Gennady Shapiro
Ranch Hand

Joined: Sep 25, 2001
Posts: 196
two remarks:
1. Consider JDBC model for accessing DB. No need to invent the bicycle -- JDBC. As Peter mentioned, each client expects a Connection interface and receives either RMIConnection or FileConnection. But since the client operates on the general Connection interface it neither knows nor cares specifically what kind of Connection it is operating on (RMI, File, JDBC, Pam Anderson).
look here:
Connection conn = ConnManager.getConnection("RMI"); // "File"
Statement st = conn.createStatement(getSearchParamsFromGUI());
String [] values = st.search;
If this is not beautiful, I dont know what is.

2. Consider an ArrayList instead of a Map. ArrayList gives you direct indexed access to your lock object, where number of the record is , in fact, its index in the list. The Map will have to calculate hash index of your lock object every time you use it, making a performance hit.
P.S. Why do people insist on using synchronized Maps when they are being accessed only by already synchronized methods? Besides, syncronized HashMap = Hashtable.
Mark Spritzler
ranger
Sheriff

Joined: Feb 05, 2001
Posts: 17249
    
    6

Thanks Peter. I was just being stupid, and not understanding your very simple and straight to the point answer.
Because the returned object is an instanceOf Remote and extends Unicast... it stays on the server.
I just couldn't understand that simple point. It actually took me 45 minutes of reading an RMI book to get that into my thick skull. )))
Thanks
Mark
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Originally posted by Gennady Shapiro:
2. Consider an ArrayList instead of a Map. ArrayList gives you direct indexed access to your lock object, where number of the record is , in fact, its index in the list. The Map will have to calculate hash index of your lock object every time you use it, making a performance hit.
Unfortunately this means that the size of the lock list is directly proportional to the size of the data - this approach is unusable in any "serious" database. Arguably, it is fine in this case because Data breaks down on large data sets anyway (esp. the find methods). Nevertheless it is easy to make a strong case for a Map.
The hashCode() for an Integer is, by the way, just the value of the integer itself, so it isn't going to any computational overhead as you seem to suggest here. More important is the fact that an implementation using a Map tends to generate more objects which have to be garbage collected.
P.S. Why do people insist on using synchronized Maps when they are being accessed only by already synchronized methods? Besides, syncronized HashMap = Hashtable.
Heartily seconded on the first point. I wouldn't replace a synchronized Map by a Hashtable, by the way; Hashtable's API is a mess because the Collections API is kludged on top of an existing object. I'd always recommend native Collections objects such as HashMap over the old-style Vector and Hashtable.
- Peter

[This message has been edited by Peter den Haan (edited October 01, 2001).]
Jason Voegele
Greenhorn

Joined: Oct 12, 2001
Posts: 9
Originally posted by Peter den Haan:
[B]A particularly elegant solution is to give each client its own Connection remote object that implements the DataInterface. This solves all your problems in one go without unnecessarily burdening the client code with tokens, additional arguments or whatever. After all, the Connection on which the method (lock, unlock, add,...) is invoked is the client identity you're looking for.

I'm a bit confused by this. If the Connection object is a true remote object, then the semantics of remote objects dictate that there is one copy of the Connection object, not one per client. Could you expound upon this?
Thanks,
Jason Voegele
Mark Spritzler
ranger
Sheriff

Joined: Feb 05, 2001
Posts: 17249
    
    6

Jason, the connection object is not bound to the Registry. If that helps out, the other thing to check out is O-Reilly's book on RMI. That is how I got over the same question that you have.
Mark
Jason Voegele
Greenhorn

Joined: Oct 12, 2001
Posts: 9
Originally posted by Mark Spritzler:
Jason, the connection object is not bound to the Registry. If that helps out, the other thing to check out is O-Reilly's book on RMI. That is how I got over the same question that you have.

Ah...that does make more sense. I was assuming that the Connection object was looked up by name from the client. Since that is not the case, this makes more sense now.
Thanks.
Peter den Haan
author
Ranch Hand

Joined: Apr 20, 2000
Posts: 3252
Precisely. The only thing you'd bind in the registry is a ConnectionFactory.
- Peter
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Lock/Unlock
 
Similar Threads
Synhronization
Lock/Unlock Implementation Review
Locking & Threading Issues...HELP!
Yes! Passed! 388/400
Implementing Lock/Unlock