Hi I m going to download assignment soon, and I tried to write lock manager now - as I understand this is one of most difficult problems. Well, I wrote it, but the question is : why does it work? Locking is processed completely on server side, no cookies are passed to client. Here is pseudocode for LockManager. Its methods lock() and unlock() are called from remote database implication. LockManager is a singleton. Every client gets a reference to RemoteDatabase object (and this is one-to-one relationship). LockManager instance is static member, and therefore clients perform concurrent sequental access to records (lock/modify/ unlock).
Its advantage is that I can test it from the same computer, starting 100 threads which connect to server using IP, not localhost. every thread gets its own ID. It is fine, but when I start it in 2 cases from 5 (approx) I get deadlock. Here is a part of log file:
..... 388 trying to unlock ...388 unlocked record Locking by 378 378 trying to unlock ...378 unlocked record < ------------ 378 called unlock() Locking by 353 353 trying to unlock ...353 unlocked record Locking by 376 376 trying to unlock ...376 unlocked record Locking by 309 Client 346 is checking if locked, lock belongs to 309 346 is waiting 378 trying to unlock ...378 unlocked record < ------------378 called unlock() <EOF>
Here numbers are parts of IDs (just substrings of "RMI TCP Connection(<number> - <my ip>" which is returned by Thread.currentThread().getName()). Notice that client 378 called unlock twice! Thats not a bug - all calls to unlock() are made only once, and anyway it happens sometimes, but not always. This is a puzzle for me. Again, notice, that before second call lock owned by 309. But 378 anyway unlocks it !!! Then program hangs. I put System.gc() in lock() method (see label 3 in pseudocode above) and deadlock disappeared. It works fine. I tested it with 100 clients more than 30 times - no problem. Log file is ok, clients wait, lock, unlock etc in sequental order. Now, I cant get whats the reason for deadlock? Why did GC made it work ? System.gc() is the thing that I dont want to use in assignement; I think it should not be used. Second, currently I cannot test LockManager from different computers. I use "loopback" calls from the same machine. How do you think, will this program work in real multiuser environment? I mean - I use current thread as ID. Will it work? I think yes, but it would be much more useful to hear your opinion. Thanks
Hi Denis, very welcome to SCJD forum. You are working on the locking before you even downloaded the assignment? This is real dedication to doing the project. Appreciate it All I can say is that we cannot depend on the garbage collector. Suppose in your case, you were saying once you included System.gc() its working else not. Then I think it is better to look it or approach the problem in a different way rather than depending on System.gc() only. Good Luck.
Hi Denis, Welcome to JavaRanch and this forum. Are you calling the lock()... unlock() methods from the *same* method? I ask you that because RMI does not guarantee that two methods on the same remote object will execute in the same thread. It means that identifying locks owners by Thread.currentThread() is a valid solution *only* if both lock() and unlock() calls are done within the same method. Something like:
Joined: Mar 22, 2004
Thanks for replies!
Are you calling the lock()... unlock() methods from the *same* method? I ask you that because RMI does not guarantee that two methods on the same remote object will execute in the same thread. It means that identifying locks owners by Thread.currentThread() is a valid solution *only* if both lock() and unlock() calls are done within the same method. Something like:
Yeah!!! You are right! I just removed all lock - unlock()s from client side; now these methods are called from setValue() on server side - it increased speed (only one remote call instead of 3) and there are no deadlocks now (at least after 15 tests with 100 clients) - without garbage collection. Cheers!