> However, how about the elements inside the arraylist itself?
[...]
> Hence, is it safe, that we declare a arraylist as volatile, and
> assume that all threads is able to get its most updated "element
> value"?
You can find some good papers on this topic here:
http://www.cs.umd.edu/~pugh/java/memoryModel/
http://gee.cs.oswego.edu/dl/cpj/jmm.html
The second of these (an excerpt from Doug Lea's Concurrent Programming
in Java, a book I highly recommend) includes the following text, which
provides a succinct answer to your question:
Declaring a reference field as volatile does not ensure visibility
of non-volatile fields that are accessed via this reference.
/gordon
--
Tom Hawtin - 20 Apr 2007 12:10 GMT
> The second of these (an excerpt from Doug Lea's Concurrent Programming
> in Java, a book I highly recommend) includes the following text, which
> provides a succinct answer to your question:
Whilst that is a very good book, it is eight years old. The JMM has been
replaced since then, and the old one didn't work anyway.
More useful is Java Concurrency in Practice (Brian Goetz with others).
But I wouldn't want to see anyone writing production code with so much
as the synchronized keyword without having read both.
> Declaring a reference field as volatile does not ensure visibility
> of non-volatile fields that are accessed via this reference.
True in 1.3. But then, IIRC, in 1.3 volatile wasn't actually implemented
at all.
For implementations from 1.4 and the spec from 1.5, there is an
equivalent guarantee (but requires the volatile to be written to by the
thread that updates the indirect fields after updating).
Tom Hawtin
> i am a bit confused on the usage of volatile keyword. [...]
> volatile ArrayList arraylist;
> For point object reference, A trying to change the object reference to
> a new ArrayList(200). B tries to read point. B will get the latest
> ArrayList(200) object since B is reading directly from true arraylist
> object reference memory location, not its cache.
Cache isn't the only important thing. If you try to use it for
'motivation' you will be led to incorrect conclusions. A more important
factor is compiler optimisations. Compilers do *really* odd and
unexpected things, so stick to Chapter 17 of JLS 3.
> However, how about the elements inside the arraylist itself? Says A
> try to change the arraylist element by
> arraylist.setElementAtLocation("new value", 37). When B tries to
^list.set(37, "new value") ?
> access the arraylist element at 37th, will it read directly from the
> true arraylist 37th element memory location, or there is a possibility
> B will read from 37th element cache memory?
You need to make assumptions about the implementation of ArrayList.
While they might be reasonable assumptions here, implementations in
general may well not do what you expect. There is an example in JBoss
where a HashMap used for logging (and therefore correctness not
necessarily that important) caused an infinite loop due to being used
concurrently.
However, for current versions of Java accessing a volatile affects
memory other than just the field declared volatile (except if you use
the weak/lazy methods in java.util.concurrent.atomic). If you write to
some fields then write to any volatile, and then in another thread read
*the same* volatile then read the fields, you will get the 'correct' answer.
However, if you just read the volatile field, nothing much is guaranteed.
> Hence, is it safe, that we declare a arraylist as volatile, and assume
> that all threads is able to get its most updated "element value"?
As long as you make some reasonable assumptions about ArrayList, you can
ensure you get updated values by inserting a write to the volatile field
after updating the element values:
public void set(int index, String value) {
List list = this.list();
list.set(index, value);
this.list = list; // <- actually important
}
However, you cannot change the ArrayList structurally and (always) get
away with it. Adding an element may cause the backing array to be
replaced in a non-thread-safe manner.
One approach is to copy the entire array before making a change (and
making sure it is updated atomically). However, if you are going to use
that you might as well just use
java.util.concurrent.CopyOnWriteArraylist (on the JSR166 backport for
1.4). Copy-on-read is a similar technique.
Anyway, for real code you are much better off using standard collections
that are thread safe. Low-level operations involving threads are very
difficult to get right and are usually done incorrectly.
Tom Hawtin