Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / April 2007

Tip: Looking for answers? Try searching our database.

does volatile works on object reference

Thread view: 
yancheng.cheok@gmail.com - 20 Apr 2007 07:14 GMT
hi all,

i am a bit confused on the usage of volatile keyword. consider the
following statement

public class Me
{
   public Me()
   {
       primitive = 0;
       arraylist = new ArrayList(100);
   }

   volatile int primitive;
   volatile ArrayList arraylist;
}

Says there are two Thread A and B, A modify primitive value to 100. B
tries to read primitive value. B will get the latest primiteve value
(100) since B is reading directly from true primitive memory location,
not its cache.
(Please correct me if the above statement is wrong)

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.
(Please correct me if the above statement is wrong)

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
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?

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"?

Thank you very much!

cheok
Gordon Beaton - 20 Apr 2007 08:01 GMT
> 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
Tom Hawtin - 20 Apr 2007 12:01 GMT
> 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


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.