Example scenario:
- Create two SynchronizedSets (s1 and s2)
- Pass them to two threads (T1 and T2)
- Start the threads
T1's run() : while (forever) s1.equals(s2)
T2's run() : while (forever) s2.equals(s1)
What happens? - SynchronizedSet's equals acquires lock on itself
It computes the length of the param that's passed in and also what it contains to determine whether that is equal [Note: this is a guess based on the logs I analyzed]
If the passed in param is also a SynchronizedSet, calls to size() and containAll() implies lock of that has to be acquired as well.
In the above example, lock acquiring orders for T1 and T2 are as follows:
T1: s1 -> s2 T2: s2 -> s1
Ofc, it leads to a deadlock.
This problem is not specific to Synchronized Collections alone. It can happen even with Hashtable or Vector.
I believe this is a Java API limitation (design). How to overcome this? How do I ensure this does not happen in my application? Is there some design principle I should follow without getting into this situation?