...-----Original Message----- From: Peter B. West [mailto:[EMAIL PROTECTED]
I've been hacking the tree methods in Node recently
Are you talking 'maintenance vs. HEAD' here?
No. I realise the message was ambiguous. I was talking about versions of my general tree-handling classes - Node (primarily) and Tree.
My first change was to synchronize the methods which had previously been synchronized on the Tree, but I realized that such synchronization of methods in inner classes probably only synchronized on the actual inner class instance, not on the containing class instance. Does anyone have any knowledge of this?
Hmm... Difficult to tell from the docs I read, so far... I'd say: indeed, unless the code-block through which the inner class (synchronized) method is accessed is synchronized on the containing class instance, no? Then again, synchronizing only on the inner classes could turn out to offer more flexibility, as other operations on the containing class can still be carried out while the inner class is locked (provided, of course, that the 'other' operations do not need access to the inner class instance...)
In this case they do need such access. The inner classes are iterators.
I was worried about increasing the probability of deadlock by having many more locks held concurrently. Without having thought about it a great deal, it seems to me that it is easier to appreciate and avoid potential deadlocks when synchronization is more "global", as with the synchronization on the containing Tree object.
It also occurred to me that optional synchronization might be a good idea, allowing a common synchronization object to be passed to the Node constructor. An alternative was to allow optional synchronization, but to synchronize on the affected Node object. On the construction of any particular Node, a boolean can be passed indicating the need for synchronization.
The other solution for the above stated issue: remove the synchronization from the inner class methods, and synchronize their bodies on the containing class instance. (Again: IIC you'd only need this if you really *need* to synchronize on the outer class... if you don't, I guess the approach you're taking now is more flexible and less likely to lead to deadlocks.)
<snip />
Does anyone have experience with such issues?
No real experience, but thinking about 'optional synchronization' brings up all sorts of ideas, like:
- a Lockable interface for Nodes - a SyncedNode extending Node implementing the Lockable interface - when you really only need a non- or partly synchronized Node use the main type; if you need a fully synchronized one, use the subtype (ratio of execution speeds from non-synced vs. synced is roughly 100 vs. 150, so it would definitely be worth it to avoid synchronization altogether where it is not strictly necessary)
This would be the clean way to express the current version of the code. However, I am still toying with the idea of allowing (sub)trees to synchronize on an object passed in as a parameter to the Node constructor. If the object reference is null, synchronization is turned off. In this scheme, I would allow subclasses (like Area) to switch synchronization on by setting the 'sync' object non-null, as, for example, when a locally constructed subtree was grafted onto the AreaTree. It also returns to the situation of a common synchronization object for each node in the (sub)tree.
Peter -- Peter B. West <http://www.powerup.com.au/~pbwest/resume.html>