On Tue, 16 Apr 2002, Jack, Paul wrote:
> Attached is a new List implementation inspired by 
> but faster than FastArrayList.  From the javadoc:

Is there any external behavior difference between FastArrayList and your
OptimizedFastArrayList (other than performance)?  If so, can you
explicitly specify the differences and why?  If not, is there a reason not 
to just replace the existing FastArrayList with the faster implementation?

> Read access to this list is not synchronized, but write
> access is.  To pull this trick off, the state of the list
> is cloned during a write, the changes are applied to the
> clone, and then the clone replaces the list's state.  Read
> operations use a local reference to the old state, and are
> not adversely affected by a write.  This is similar to 
> org.apache.commons.collections.FastArrayList.

is it me, or does this behavior suffer from the double checked locking
problem?  While this isn't the exact same scenario (i.e. the double
checking of a variable one in and one outside a synchronized block), I
believe the situation is the same:  it is possible that a non-synchronized
read can see the cloned object before that cloned object is fully created.

For more information on the double checked locking, see this excellent 
writeup: 
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Other writeups:
http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html
http://www.javaworld.com/javaworld/jw-05-2001/jw-0525-double.html

The JSR for "fixing" the Java memory model:
http://jcp.org/jsr/detail/133.jsp

[Paul, I don't mean to pick on you about this.  The existing Fast* classes 
suffer from the exact same problem]

> However, since the list is backed by a dynamic array, *many
> of the algorithms that alter the list already require that 
> the state be cloned*.  For instance, to remove an element, 
> a new array must be allocated, and the elements from the old
> array (minus the removed object) must be copied to the new 
> array.  FastArrayList essentially performed the cloning twice:
> It first clones the entire list, and then performs the costly
> remove() operation on the copy.  This implementation is 
> optimized such that a new array is only allocated once.  
> Assuming no monitor contention, this class should perform 
> similarly to java.util.ArrayList, except for the add(Object)
> and set(int, Object) methods, which now perform in linear time.

Actually, if the ArrayList implementeds were smart, they aren't "cloning"  
the array each time, they are just adding the element in an existing, but
empty, slot in the array.  That is, the underlying array is possibly
larger than ArrayList.size().  An add(Object) only needs to duplicate the
array if the existing array is full.  An add(int, Object) may need to
"move" elements, but shouldn't need to clone the entire array.  The actual
cloning of the array (to grow or shrink the size) can have an amortized
constant time operation if the the array is doubled when a grow is
required (and if you add in the shirnking, which I don't think the JDK
impl does, you would halve the size of the array when it is 1/4 full).

In your version, you may even be able to get rid of the single clone using
a similar technique.  For example, if you are adding to the end
(add(Object)), if the array already has room for one more element, you
could just increase the size and create a new State rather than a new
State *and* a new array.  When removing the last element, use the same
array, but create a new State with the smaller size.  I'm not sure if that
really buys much though, as it requires excess memory for the empty array
elements that are only used if an add operation occurs sometime in the
future.  Considering that the underlying ArrayList impl uses that memory 
anyway, I'm not sure this is that big of a deal when considered as a 
replacement of FastArrayList. 

regards,
michael


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to