[concurrency-interest] question the about the JMM

Joe Bowbeer joe.bowbeer at gmail.com
Wed Dec 5 15:11:35 EST 2007


as i've already replied offlist, if both methods are called by
separate threads without additional sync than what is shown,
visibility of the flag value is not guaranteed. i recommend volatile.

On 12/5/07, Peter Veentjer <alarmnummer at gmail.com> wrote:
> I'm having a discussion with a a very smart colleague about some
> example (from iBatis) that in my opinion has a visibility problem and
> in his opinion doesn't.
>
> This is the example:
>
>  private boolean flag = true;
>
>  public void something() {
>    if (flag) {
>      synchronized (this) { // synchronized block
>        // do something
>      }
>    } else {
>      // do something else with very little impact, NOT inside a
>  synchronized block
>    }
>  }
>
> public void setFlag(boolean newFlag) {
>    this.flag = newFlag;
>    synchronized (new Object()) { // ANOTHER MONITOR THAN IN METHOD something
>      // unimportant
>    }
>  }
>
> With my current understanding of the JMM I would expect that the flag
> variable has a visibility problem. Because there is no happens before
> relation between the write in the setFlag method, and the read in the
> something method, a thread that runs the something method doesn't need
> to see the written value by a different thread ever.
>
> The problem could be solved by using the the monitor lock rule (using
> the lock of the object itself) or the volatile read/write rule. So the
> simplest thing to remove the visibility problem is to make the flag
> volatile.
>
> The question is, am I correct? Does this example contain a visibility
> problem?
>
> To make things more complicated, we have asked Brian Goetz and
> according to him my colleague is right.
>
> this is the mail conversion between them:
>
> rom: Brian Goetz [mailto:brian at briangoetz.com]
> Sent: Wed 12/5/2007 16:41
> To: Erwin Bolwidt
> Subject: Re: JMM question (wrt to a statement you made at JavaPolis)
>
> Your colleague is wrong.
>
> Both of the statements you refer to are correct.  The key is that only
> synchronization actions (reads and writes of volatiles, and acquire and
> release of locks) need to be totally ordered.  So if thread A release a
> lock "before" thread B acquires one, that doesn't mean anything, because
> the threads don't share your concept of "before".
>
> The primary mistake people make in approaching concurrency is to falsely
> assume "sequential consistency", meaning that "everything happens in a
> fixed, global order".  In reality, it is more like the thought
> experiments you did in special relativity, where ordering is relative to
> the observer.  This happens in modern CPUs too, in the absence of
> adequate synchronization.  The only total ordering you can rely on is
> synchronization actions.  This is why if we synchronize on a common
> lock, things work properly -- because it is sensible to speak of "when
> you release the lock and I subsequently acquire it."  When we acquire
> different locks, there is no way to guarantee "subsequent".  (And when
> we don't acquire locks at all, it isn't even meaningful to talk about
> "subsequent.")
>
> Any logic that relies on unsynchronized reads of shared references to
> mutable objects is committing the same error as double-checked locking,
> with the same possible consequences.
>
> The rules for the new memory model (happens-before) are actually fairly
> simple to reason through.  Its the "I (think I) know what's going on in
> the machine" part that leads people into trouble.  Such reasoning
> invariably amounts to "I don't believe these are really the rules."
>
> Erwin Bolwidt wrote:
> > Hi Brian,
> >
> > A collegue and are having a discussion about one aspect of the new Java
> > Memory Model.
> > After one of your presentations on the JMM I asked you about how
> > specific volatile or synchronized is (at JavaPolis I believe but it
> > could have been JavaOne)
> >
> > Specifically, I wondered if synchronized on different monitors or access
> > to different volatile variables were really independent: if these would
> > only cause related data to be synchronized (written out to/invalidated
> > L1/2 caches) with "global" memory or if they would effectively
> > synchronize the whole thread state (caches) with "global" memory.
> > You response as I remember it was that the latter was the case: the
> > whole thread state (caches) would be synchronized. The former would be
> > too complicated to implement.
> >
> > The JSR 133 FAQ (co-authored by you) at
> > http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html states:
> >
> >         *Important Note:* Note that it is important for both threads to
> >         synchronize on the same monitor in order to set up the
> >         happens-before relationship properly. It is not the case that
> >         everything visible to thread A when it synchronizes on object X
> >         becomes visible to thread B after it synchronizes on object Y.
> >         The release and acquire have to "match" (i.e., be performed on
> >         the same monitor) to have the right semantics. Otherwise, the
> >         code has a data race.
> >
> > Now I realize that possibly both statements are true, and that this
> > boils down to a misunderstanding of terms like "happens-before
> > relationship".
> >
> > I have an example and I'm not sure what would happen here. In the real
> > case, "flag" was called "cacheEnabled" and the question was whether the
> > cache could be turned off in a way that would be guaranteed to work.
> > This looks a little like the double-check locking issue. My statement
> > was that if "setFlag(false)" was called on one thread, the something()
> > method on another thread would be guaranteed to see this
> > _the_second_time_ the method was entered, because the synchronization
> > would invalidate the CPU caches on the thread that runs something(), and
> > likewise the synchronized on a different monitor in setFlag would write
> > out the change to the field "flag" to global memory.
> >
> > My collegue disagrees. Can you tell who is right?
> >
> > Thanks a lot if you can spend some time on this.
> >
> > Regards,
> >   Erwin Bolwidt
> >
> > -------------- Example code --------------
> >
> > private boolean flag = true;
> >
> > public void something() {
> >   if (flag) {
> >     synchronized (this) { // synchronized block
> >       // do something
> >     }
> >   } else {
> >     // do something else with very little impact, NOT inside a
> > synchronized block
> >   }
> > }
> >
> > public void setFlag(boolean newFlag) {
> >   this.flag = newFlag;
> >   synchronized (new Object()) { // ANOTHER MONITOR THAN IN METHOD
> something
> >     // unimportant
> >   }
> > }
> >
> >
> > --
> > Erwin Bolwidt
> > business consultant
> >
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at altair.cs.oswego.edu
> http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
>


More information about the Concurrency-interest mailing list