I just got the assignment. But I have not any idea how to implement these two methods, Is there anyone who can give me some hints? any idea is appreciated.
public void lock(int record) public void unlock(int record) Record locking must be implemented using the methods public void lock(int) and public void unlock(int). These methods are required to allow concurrent use of the database when booking flights from multiple clients. Note that the locking required is effectively a "write" lock only. If updates occur to a record that is being displayed on another client, then no change occurs at the other client. However, if two clients attempt to perform the sequence lock,read,modify,write,unlock concurrently, then both modification attempts will be handled correctly. The aim is to ensure that if two customers attempt to book a seat on the same flight concurrently, then the number of available seats is definitely reduced by two, unless there was only one seat, in which case, one customer will be advised at booking time that no more seats are available. The lock method should block until the requested lock can be applied. The integer argument indicates the record to be locked. The unlock method simply removes the lock from the specified record. If an attempt is made to unlock a record that has not been locked by this connection, then no action is be taken.
Tony, Essentially, you need to keep some collection of current locks. The minimum info for a lock is the record number it applies to (or whether it applies to the entire database). All methods that modify data must check to ensure that an appropriate lock exists. lock() and unlock() also have to check the existing locks, of course. One big design question is whether you're going to trust clients to lock a record before doing modification - if you don't, then you also have to keep some sort of client identifier with each lock. My design keeps track of which client has which lock; other people have passed without doing this. jply
jerry, i have seen a lot of discussion about identifier of each client concerning the lock\unlock problem. i don't understand why you guys really need an identifier for specific client? isn't it clearly written in the Sun's requirement that you must implement lock(), unlock() only using recordNumber as parameter and void as return value? my design is let the jvm do synchrinization for each locker so that you dont need any identifier for clients. it seems that we might need an identifer for each client if we are going to implement a queue for each locker. in this case, we have to use something to distinguish clients to achieve the goal that first come, first serve. the queue seems more attractive than normal object synchrinization, however if it's impossible to implement a queue without modifying the signature of lock(), unlock(), i certainly will give up a queue design for each locker. what do you think jerry? can you clarify why you have to use client's unique identification (i dont think it really does matter which side you will implement the lock, unlock functionality.) cheers! /rong
queue seems more attractive since in normal object synchrinization, notify() doesnt hornor the coming sequence of locker requeust threads. in bad case, it can happen like this, thread A first grabs the locker, thread B comes aftetr A, so it has to wait, thread C comes later than B but possible get locker after A release locker and call notify(), then Thread D comes, after C finish its business, it calls notify(), guess what, D could get notified but not B, poor B.. tell me if i am wrong about this.. /rong
Rong, You seem to be making the assumption that synchronizing access to all code that modifies the db is sufficient. I decided not to go with that assumption for several reasons: 1) Sun specifically mentioned in my instructions that I was to implement lock() and unlock, 2) Sun mentioned the sequence "lock, read, modify, write, unlock", which implies that the record should remain locked between lock() and unlock() calls, not just while the client is in a single data modification method, and 3) I don't like the idea of a server trusting clients to behave appropriately. I'll elaborate on #3: If you trust clients to behave, and never call a modification method without first calling lock(), you can just have the modification methods reject any calls unless lock() has been called for that record and unlock() hasn't. If you don't trust them (I don't - who knows what kind of future clients might be written?) then the modification methods must somehow verify that the client calling them is the one with the lock, or one client could lock a record and another one (the bad boy) could modify it. A final note: The instructions from my assignment say "Record locking must be implemented using the methods public void lock(int) and public void unlock(int)", but they don't say you have to implement them in Data. I don't want to be explicit, but that should hint at one possible solution. I'm not sure what you mean when you say "let the jvm do synchronization for each locker". Are you thinking about grabbing a synchronization lock in lock() and keeping it until unlock()? How would that work? The sync lock would be relinquished when the lock() method returns. Also remember that, at least in an RMI server, you can't depend on all requests from a single client being handled in the same thread. What if RMI placed the client's modify() call in a different thread than its lock() call? Can you elaborate on what you're thinking about? As to whether to use a queue, I eventually decided not to do that, but it's a good idea. I decided that the server could handle requests fast enough that the delay any client experienced from random lock granting would be small compared to network latency, unless the number of simultaneous clients was huge. But a queue (per lock) would make the server behave more correctly. Hope this discussion helped, or at least was entertaining. Jerry
Jerry, First, I didn't assume that synchronizing access to all code that modifies the db is sufficient. Second, I don't like the idea of a server trusting clients to behave appropriately either. That's way I implemented lock()/unlock() at server side. The rmi interface I defined for client is an all-in-one method: seserveSeat(), inside it is sequential lock(), doBooking(), unlock(). So the client would never call lock/unlock directly, the server takes care of it. Even though, I didn't need any client identifier. I will just follow the specs of my assignment - "Record locking must be implemented using the methods public void lock(int) and public void unlock(int)". The only disadvantage of this design is that I can't implement queue(FIFO) for each locker. But, after all, I don't want to introduce more complexities at the same time violating Sun's specs. >I'm not sure what you mean when you say "let the jvm do synchronization for each locker". : I have my own locker class for every record and rely on wait() and notify(). >Are you thinking about grabbing a synchronization lock in lock() and keeping it until unlock()? How would that work? The sync lock would be relinquished when the lock() method returns. : Yes, it's exactly what I am doing and it works. The sync monitor will be relinquished when the lock() method returns of course, so other clients can have chance to enter lock() block and then be blocked or not according to the status of the locker. >Also remember that, at least in an RMI server, you can't depend on all requests from a single client being handled in the same thread. What if RMI placed the client's modify() call in a different thread than its lock() call? : As I said before, I put lock(), doBooking(), unlock() in the same RMI method and implemented on server side, the problem you mentioned would never appear. Cheers! /Rong
Rong, Aha! Now I see where you're coming from; sorry for the misunderstanding. I didn't realize you were exporting a reserveSeat() method. I thought about that one long and hard. It does make the operation atomic from the client's point of view. My instructions, however, said "To connect with your server, you should create a client program. This implementation should include a class that implements the same public methods as the suncertify.db.Data class, although it will need different constructors to allow it to support the network configuration." I understood this to mean that I should write a generic Data server and handle the schema-specific details in the client. After all, if the client has to implement modify() I guess it should use it, too. Jerry
Tony, If you synch the vector, when one client wants to lock item 1, at the same time the other client can't lock item 2, because the "container" m_lock is locked. If you don't use client ID, when client one gaints a lock, client two can unlock it, because the monitor doesn't know who is whome. Paul
Originally posted by tony lu: yes, I have to synchronize the unlock too. thank you for you response
[This message has been edited by liu ye (edited January 11, 2001).]
Liu, Yes you can, you can lock other records because wait () releases the lock (the current thread temporarily leaves the monitor and waits for the condition to change state) on the vector and the synch code is exited so other threads can enter the monitor and acquire the lock. The wait() method is implemented as follows: mutex(lock).release() condition.wait_for_true //wait here mutex(lock).acquire() [This message has been edited by Manuel Palacio (edited January 13, 2001).] [This message has been edited by Manuel Palacio (edited January 13, 2001).]
Hi Guys, I know you guys are taking totally different solution on the position of calling lock() and unlock(). Both of the solutions have their own advantage. 1. call at client side follow sun's implication. and it will close to passing exam in theory. but some problem is really there. Record will be locked for ever when clients crashed after calling lock() without call unlock(). 2. call at server side against sun's implication. but it's more reasonable. it's an atomic solution. avoid to deadlock a record. Maybe Sun implies us to implement an generic DB server. but Sun is more explicitly tell us to implement an traditional client-server application. For such an application we are not supposed to put all business logic method at client side. We can certainly put some business logic method at server side. Let's say bookSeat() just like a stored procedure we put at server side. Do you guys think Sun will penish this idea that is not stupid? I really take the second solution mentioned above. My key question is will I be punished to fail the exam by taking the second solution. Do you guys know if there are somebody to pass the exam by taking the second solution. thanks for reply Dasong :roll: [ April 08, 2002: Message edited by: Dasong ]
Some of the following posts might give you some ideas about what the options are and what the positive and negative aspects are. As always, all could be correct (for a given value of correct ) - the more important aspect is that you should be able to justify your choice in your design document (and possibly on the exam if it crops up).