Results 1 to 10 of 10
  1. #1
    blackblizzard is offline Member
    Join Date
    Feb 2010
    Posts
    5
    Rep Power
    0

    Default Is AtomicReferenceArray<T> equivalent to Array<AtomicReference<T>>?

    Hi everyone.

    I'd like to know this and I can't find the info anywhere: is an AtomicReferenceArray<T> equivalent to an Array<AtomicReference<T>>? What do you think?

    An AtomicReferenceArray is an array of object references in which elements may be updated atomically.
    An AtomicReference is an object reference that may be updated atomically.

    So it would be equivalent, I guess? It doesn't say if in an AtomicReferenceArray there are more operations (other than access to the elements) that are also atomic.

    Atomicity is tricky. ;)

  2. #2
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,371
    Blog Entries
    7
    Rep Power
    20

    Default

    On an ordinary array two different elements can be updated simultaneously whether or not they are AtomicReferences but on AtomicReferenceArray only one element can be updated at one time.

    kind regards,

    Jos

  3. #3
    blackblizzard is offline Member
    Join Date
    Feb 2010
    Posts
    5
    Rep Power
    0

    Default

    Ah, you see, there had to be something :)
    Thanks a lot!

  4. #4
    blackblizzard is offline Member
    Join Date
    Feb 2010
    Posts
    5
    Rep Power
    0

    Default

    Actually now I'm not sure at all that's true... AtomicReferenceArray<E> is "An array of object references in which elements may be updated atomically", which seems to imply the atomicity is on the elements, not the array as a whole. In no place does it say that you cannot update two different elements simultaneously.

    What's more, check out the implementation of AtomicReferenceArray<E>'s getAndSet:

    Java Code:
    public final E getAndSet(int i, E newValue) {
        while (true) {
            E current = get(i);
            if (compareAndSet(i, current, newValue))
                return current;
        }
    }

    Where get(i) is a call to:

    Java Code:
    public final E get(int i) {
        return (E) Unsafe.getUnsafe().getObjectVolatile(array, rawIndex(i));
    }

    And the underlying structure for the array is simply:

    Java Code:
    private final Object[] array;

    I don't see how this protects from simultaneous writes on different elements. Any insights?

    Btw, I don't know how to remove the [SOLVED] tag in the title of the thread. Is it possible?

  5. #5
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,371
    Blog Entries
    7
    Rep Power
    20

    Default

    I checked Doug Lea's code (he invented all this concurrent business) and according to his code, the getters and setters etc. synchronize on on the object and so on the entire array. An array of AtomicReferences makes the access per element atomic.

    kind regards,

    Jos

    ps. Sun uses a com.sun.Unsafe class under the hood; I don't know what it does ...
    Last edited by JosAH; 02-11-2010 at 05:46 PM.

  6. #6
    blackblizzard is offline Member
    Join Date
    Feb 2010
    Posts
    5
    Rep Power
    0

    Default

    Hi JosAH, thanks for answering again :)
    You're right, in Doug Lea's code it's definitely synchronizing on the entire array -- however the Sun implementation doesn't seem to work that way... that's weird. I just don't see anywhere in the implementation how it would protect from access on the array, and not on the elements. I post the entire class below in case anyone wants to check it out.
    Btw, what Unsafe does is offering a way to access memory "unsafely", for example
    Java Code:
    getObjectVolatile(Object obj, long offset)
    "retrieves the value of the object field at the specified offset in the supplied object with volatile load semantics", where "volatile load semantics" = "fresh from memory instead of the cache". The unsafe aspect of it is that if you give an invalid offset you'll access parts of memory you shouldn't be accessing.

    Now here goes AtomicReferenceArray:

    Java Code:
    /*
     * @(#)AtomicReferenceArray.java	1.12 06/06/15
     *
     * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
     * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     */
    
    package java.util.concurrent.atomic;
    import sun.misc.Unsafe;
    import java.util.*;
    
    /**
     * An array of object references in which elements may be updated
     * atomically.  See the {@link java.util.concurrent.atomic} package
     * specification for description of the properties of atomic
     * variables.
     * @since 1.5
     * @author Doug Lea
     * @param <E> The base class of elements held in this array
     */
    public class AtomicReferenceArray<E> implements java.io.Serializable {
        private static final long serialVersionUID = -6209656149925076980L;
    
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        private static final int base = unsafe.arrayBaseOffset(Object[].class);
        private static final int scale = unsafe.arrayIndexScale(Object[].class);
        private final Object[] array;
    
        private long rawIndex(int i) {
            if (i < 0 || i >= array.length)
                throw new IndexOutOfBoundsException("index " + i);
            return base + i * scale;
        }
    
        /**
         * Creates a new AtomicReferenceArray of given length.
         * @param length the length of the array
         */
        public AtomicReferenceArray(int length) {
            array = new Object[length];
            // must perform at least one volatile write to conform to JMM
            if (length > 0)
                unsafe.putObjectVolatile(array, rawIndex(0), null);
        }
    
        /**
         * Creates a new AtomicReferenceArray with the same length as, and
         * all elements copied from, the given array.
         *
         * @param array the array to copy elements from
         * @throws NullPointerException if array is null
         */
        public AtomicReferenceArray(E[] array) {
            if (array == null)
                throw new NullPointerException();
            int length = array.length;
            this.array = new Object[length];
            if (length > 0) {
                int last = length-1;
                for (int i = 0; i < last; ++i)
                    this.array[i] = array[i];
                // Do the last write as volatile
                E e = array[last];
                unsafe.putObjectVolatile(this.array, rawIndex(last), e);
            }
        }
    
        /**
         * Returns the length of the array.
         *
         * @return the length of the array
         */
        public final int length() {
            return array.length;
        }
    
        /**
         * Gets the current value at position {@code i}.
         *
         * @param i the index
         * @return the current value
         */
        public final E get(int i) {
            return (E) unsafe.getObjectVolatile(array, rawIndex(i));
        }
    
        /**
         * Sets the element at position {@code i} to the given value.
         *
         * @param i the index
         * @param newValue the new value
         */
        public final void set(int i, E newValue) {
            unsafe.putObjectVolatile(array, rawIndex(i), newValue);
        }
    
        /**
         * Eventually sets the element at position {@code i} to the given value.
         *
         * @param i the index
         * @param newValue the new value
         * @since 1.6
         */
        public final void lazySet(int i, E newValue) {
            unsafe.putOrderedObject(array, rawIndex(i), newValue);
        }
    
    
        /**
         * Atomically sets the element at position {@code i} to the given
         * value and returns the old value.
         *
         * @param i the index
         * @param newValue the new value
         * @return the previous value
         */
        public final E getAndSet(int i, E newValue) {
            while (true) {
                E current = get(i);
                if (compareAndSet(i, current, newValue))
                    return current;
            }
        }
    
        /**
         * Atomically sets the element at position {@code i} to the given
         * updated value if the current value {@code ==} the expected value.
         * @param i the index
         * @param expect the expected value
         * @param update the new value
         * @return true if successful. False return indicates that
         * the actual value was not equal to the expected value.
         */
        public final boolean compareAndSet(int i, E expect, E update) {
            return unsafe.compareAndSwapObject(array, rawIndex(i),
                                             expect, update);
        }
    
        /**
         * Atomically sets the element at position {@code i} to the given
         * updated value if the current value {@code ==} the expected value.
         *
         * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
         * and does not provide ordering guarantees, so is only rarely an
         * appropriate alternative to {@code compareAndSet}.
         *
         * @param i the index
         * @param expect the expected value
         * @param update the new value
         * @return true if successful.
         */
        public final boolean weakCompareAndSet(int i, E expect, E update) {
            return compareAndSet(i, expect, update);
        }
    
        /**
         * Returns the String representation of the current values of array.
         * @return the String representation of the current values of array.
         */
        public String toString() {
            if (array.length > 0) // force volatile read
                get(0);
            return Arrays.toString(array);
        }
    
    }

  7. #7
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,371
    Blog Entries
    7
    Rep Power
    20

    Default

    I guess that the getObjectVolatile and putObjectVolatile methods take care of the locking of those array objects. But it is just a guess of course ... but then again, Sun has always been quite proficient in obfuscating their code ;-)

    kind regards,

    Jos

    ps. I just noticed that your link shows the API documentation for GNU's classpath code; GNU's classpath is full of errors (first hand experience)
    Last edited by JosAH; 02-12-2010 at 08:44 AM.

  8. #8
    blackblizzard is offline Member
    Join Date
    Feb 2010
    Posts
    5
    Rep Power
    0

    Default

    Quote Originally Posted by JosAH View Post
    I guess that the getObjectVolatile and putObjectVolatile methods take care of the locking of those array objects. But it is just a guess of course ... but then again, Sun has always been quite proficient in obfuscating their code ;-)
    I don't know, I'd expect them to lock the element that's being accessed, not the entire array... But we'll never know :rolleyes:, I can't find the source code for Unsafe.

    Quote Originally Posted by JosAH View Post
    ps. I just noticed that your link shows the API documentation for GNU's classpath code; GNU's classpath is full of errors (first hand experience)
    Thanks for the warning, I'll keep it in mind.

    And again, thanks for your input!

  9. #9
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,371
    Blog Entries
    7
    Rep Power
    20

    Default

    Quote Originally Posted by blackblizzard View Post
    I don't know, I'd expect them to lock the element that's being accessed, not the entire array... But we'll never know :rolleyes:, I can't find the source code for Unsafe.
    I don't know either; my reasoning is just (incomplete) induction: if Sun's code works identical to Doug's code that Unsafe object has to lock the entire array. I can't find the source code for that class either ...

    Thanks for the warning, I'll keep it in mind.

    And again, thanks for your input!
    Be especially careful with GNU's implementation of the EnumSet; it's a mess and mainly incorrect: they wanted to implement it using BitSets (as Sun did originally) but they did it wrong.

    And you're welcome of course.

    kind regards,

    Jos

  10. #10
    robvarga is offline Member
    Join Date
    Dec 2010
    Posts
    1
    Rep Power
    0

    Default

    Hi All,

    It is roughly equivalent to array of AtomicReferences, except that you don't replace the AtomicReference wrappers themselves.

    So you can handle each element with atomic operations, independently of other elements.

    Doug Lea's backported class most likely was synchronizing on the array level, because short of creating a lock object per element (which in most cases is not wanted), there is no element level object to synchronize on. It cannot synchronize on the element value object itself, because it can be replaced and it can be null, so semantics would not be correct.

    Best regards,

    Robert

Similar Threads

  1. VB Net FIX equivalent?
    By bullstreetboy in forum New To Java
    Replies: 3
    Last Post: 04-06-2009, 05:31 PM
  2. M$ (.NET) Form Load() event equivalent in SWT
    By erosszz_jp@yahoo.co.jp in forum SWT / JFace
    Replies: 0
    Last Post: 02-16-2009, 03:35 AM
  3. [SOLVED] Java equivalent to X11 Work Procedure
    By LongHitter in forum New To Java
    Replies: 0
    Last Post: 01-12-2009, 11:36 AM
  4. Replies: 1
    Last Post: 11-21-2007, 12:18 PM
  5. Php explode function, equivalent java
    By fernando in forum Advanced Java
    Replies: 1
    Last Post: 07-31-2007, 05:44 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •