[concurrency-interest] question the about the JMM

Peter Veentjer alarmnummer at gmail.com
Wed Dec 5 15:26:10 EST 2007


Hi Joe,

I'm grateful for your answer.

The reason why I'm reposting the example on the mailinglist is that my
colleague didn't believe it after I told him your answer (and gave him
all my arguments). After a lot of mailbased discussion he decided to
write a mail to Brian Goetz and Brian told him that he was right. That
is why I decided to get a more detailed answer to convince him that
reasoning in 'caches and invalidation' is not the way to go with the
new JMM. Everything is defined in happens before relations and
according to that definition, I think I'm right (in the example there
is no happens before relation between the write and the read, so
visibility problem).

My impression is that the question he asked to Brian, is not the one
we discussed about (so there is some confusion). The question Brian is
answering is that when a thread releases a lock, or does a volatile
write, all changes within that thread are visible (and maybe even
changes that occurred after) within a different thread that does the
acquire lock or volatile read. This is something I also agree on;
without this property it would be impossible to do a safe hand off for
example.

ps:
This happens before relation only is true when the lock
release/acquire is done on the same monitor.. or on the same volatile
variable.

On Dec 5, 2007 9:11 PM, Joe Bowbeer <joe.bowbeer at gmail.com> wrote:
> 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