[concurrency-interest] Thread safety of WeakReference .get() method?

Stanimir Simeonoff stanimir at riflexo.com
Wed Aug 8 05:39:39 EDT 2012


> In the absence of explicit barriers, this seems to be the work for
> non-yet-existing
> Unsafe.getOrderedObject(), which should just require VM to omit
> speculative reads and re-read memory on every get().
>
> Would that be a load-load barrier as putOrderedObject is store-store?

Stanimir



> -Aleksey.
>
> On 08/08/2012 12:24 PM, Dr Heinz M. Kabutz wrote:
> > Looks like common sense has yet again not prevailed.  In this little
> > test, I am calling WeakReference.get() in a tight loop from one thread,
> > called "readerThread".  Since the "referent" field inside the
> > WeakReference is not volatile and there is no synchronization at all for
> > that field, the "readerThread" eventually inlines the method call to
> > get() and caches the value of the "referent" field.  The "queueReader"
> > thread calls "remove()" from the ReferenceQueue and wakes up pretty
> > quickly after we have set the field "str" to null and invoked
> > System.gc().  Interestingly, The Object is finalized even though the
> > readerThread still has a reference to it!
> >
> > If you run this with the -server flag, the program will not finish.
> > With -client it finishes, because it does not cache the referent field
> > value in the readerThread.
> >
> > import java.lang.ref.*;
> >
> > public class WeakReferenceTest {
> >   private static Object str = new Object() {
> >     public String toString() {
> >       return "The Object";
> >     }
> >
> >     protected void finalize() throws Throwable {
> >       System.out.println("The Object is being finalized");
> >       super.finalize();
> >     }
> >   };
> >   private final static ReferenceQueue<Object> rq =
> >       new ReferenceQueue<Object>();
> >   private final static WeakReference<Object> wr =
> >       new WeakReference<Object>(str, rq);
> >
> >   public static void main(String[] args)
> >       throws InterruptedException {
> >     Thread reader = new Thread() {
> >       public void run() {
> >         while (wr.get() != null) {
> >         }
> >         System.out.println("wr.get() returned null");
> >       }
> >     };
> >
> >     Thread queueReader = new Thread() {
> >       public void run() {
> >         try {
> >           Reference<? extends Object> ref = rq.remove();
> >           System.out.println(ref);
> >           System.out.println("queueReader returned, ref==wr is "
> >               + (ref == wr));
> >         } catch (InterruptedException e) {
> >           System.err.println("Sleep interrupted - exiting");
> >         }
> >       }
> >     };
> >
> >     reader.start();
> >     queueReader.start();
> >
> >     Thread.sleep(1000);
> >     str = null;
> >     System.gc();
> >   }
> > }
> >
> >
> > Output with Server HotSpot:
> >
> > The Object is being finalized
> > java.lang.ref.WeakReference at 72ebbf5c
> > queueReader returned, ref==wr is true
> >  -- VM does not end
> >
> >
> > Output with Client HotSpot:
> >
> > The Object is being finalized
> > wr.get() returned null
> > java.lang.ref.WeakReference at 110769b
> > queueReader returned, ref==wr is true
> >
> >
> > Conclusion:
> >
> > The "referent" field in java.lang.ref.Reference should probably be
> > marked as "volatile".
> >
> > Regards
> >
> > Heinz
> > --
> > Dr Heinz M. Kabutz (PhD CompSci)
> > Author of "The Java(tm) Specialists' Newsletter"
> > Sun Java Champion
> > IEEE Certified Software Development Professional
> > http://www.javaspecialists.eu
> > Tel: +30 69 75 595 262
> > Skype: kabutz
> >
> >
> >
> > On 8/7/12 4:49 PM, Aleksey Shipilev wrote:
> >> On 08/07/2012 04:47 PM, Raph Frank wrote:
> >>
> >>
> >>> The documentation says that once an object has been determined to be
> >>> garbage collectable, "At that time it will atomically clear all weak
> >>> references to that object", so presumably, the get method can be
> >>> called, some if is atomically set to null?
> >>>
> >> I think the real meaning behind that claim is "atomically set *all* weak
> >> references to that object", i.e. two weak references to the same object
> >> will simultaneously become clear once object is not reachable.
> >>
> >> Mutator threads are not modifying the referent, and so the real question
> >> should be: is it possible to read the non-null referent after weak
> >> reference is cleared? There is no difference how many user threads are
> >> accessing now, because the possible race is between mutator threads and
> GC.
> >>
> >> The answer to that is VM-specific. Common sense is that all GC
> >> operations should be committed before returning back to the mutator
> >> after stop-the-world, or notified to the mutator as soon as possible in
> >> concurrent GCs. If that wasn't true, WeakRefs would risk keep
> >> referencing the objects that are not really there, and it would broke
> >> too many applications already.
> >>
> >> -Aleksey.
> >>
> >> _______________________________________________
> >> Concurrency-interest mailing list
> >> Concurrency-interest at cs.oswego.edu
> >> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
> >>
> >>
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20120808/19b4e382/attachment-0001.html>


More information about the Concurrency-interest mailing list