I was reading stuff about "Reentrant Lock" . There was problem of "Deadlock" which is being solved by "tryLock()" mechanism provided in reentrant locks.
Problem : 2 threads trying to make a transfer from One account to another and got deadlocked because One thread acquires lock on Account1 Object (waiting for lock on account 2 object ) and another thread acquires lock on Account2 object.(and waiting for lock on account1 object).
Provided Solution : The problem is being solved by making a method from which Thread returns only if it acquires lock on both the Account Object or get trapped in that method until it returns. I understand that solution. But here goes
my way of solving the same problem.
My Solution : The whole problem of deadlock came in because of acquiring the locks by threads in different order and there were 2 locks involved. So i thought of making use of Factory which gives me a "Representative Object" against the two account objects whose lock i want. Moreover this Factory will use "Singleton pattern" as well so that it returns the same object for these two objects.
So now since we have "One Representative" object , we need only one Lock and hence there is no problem of Deadlock. So sequence would be like this
Thread 1 will get instance from Factory which represents 2 Account objects.
Thread1 Locks it.
Thread 2 will get instance from Factory which represents 2 Account objects. ( Since singleton pattern is used, it will get the same object )
Thread 2 will block on "Representative Object" .
Please let me know, whether this solution is fine or i am missing something .
We would have to see implementation to be sure but here are things you should consider:
1) Are there cases where code is locking on just one of the Accounts? Should locking on this double lock synchronize with the single Account locks?
2) You need to make sure that the locks are recorded independent of order. For example, if you have a method like this: public static Lock getDoubleLock(Account acnt1, Account acnt2) that you get the same lock independent of order. Example if someone calls it like getDoubleLock(bob, jane) and getDoubleLock(jane, bob) the same lock should be returned.
3) Make sure that you properly synchronize the making and getting of the Locks. You wouldn't want to get different Locks in different threads.
An additional thing to consider: What happens if there are three accounts (mary, bob, jane) and one thread calls getDoubleLock(mary, bob) and an other thread calls getDoubleLock(jane, bob) ? As far as I understand the proposed solution, this will leave the account 'bob' not synchronized, as there is a lock for (mary, bob) and a different one for (jane, bob).
As accounts usually have a unique identifier, a solution would be to always lock the account with the 'lower' identifier first.