Memory Consistency Errors

E

Eric Sosman

mei wrote On 02/13/07 14:26,:
Hi,
While reading the tutorial
http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html,
something caught my attention:
It is said that memory consistency errors can occur even when atomicity
of reading/writing access is guaranteed with volatile.
However they don't develop this matter.
Is there somebody that could explain me more how could this happen?
Thank in advance.

Accesses to main memory might not occur in the same
order that the CPU initiated them, particularly for writes
(which often go through hardware write buffers so the CPU
needn't wait for them). If CPU 1 writes the Answer to
location A and then writes the AnswerIsReady flag to B,
CPU 2 may see the change to B before it sees the change
to A, and thus get the WrongAnswer. Making either or both
writes atomic doesn't help; what's needed is something
called a "memory barrier."
 
K

Knute Johnson

mei said:
Hi,
While reading the tutorial
http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html,
something caught my attention:
It is said that memory consistency errors can occur even when atomicity
of reading/writing access is guaranteed with volatile.
However they don't develop this matter.
Is there somebody that could explain me more how could this happen?
Thank in advance.

I looked and couldn't find the reference you mentioned. Do you have the
URL of the page you saw that on?

Thanks,
 
K

Knute Johnson

Eric said:
mei wrote On 02/13/07 14:26,:

Accesses to main memory might not occur in the same
order that the CPU initiated them, particularly for writes
(which often go through hardware write buffers so the CPU
needn't wait for them). If CPU 1 writes the Answer to
location A and then writes the AnswerIsReady flag to B,
CPU 2 may see the change to B before it sees the change
to A, and thus get the WrongAnswer. Making either or both
writes atomic doesn't help; what's needed is something
called a "memory barrier."

Is that not what you get with volatile?
 
L

Lew

Knute said:
I looked and couldn't find the reference you mentioned. Do you have the
URL of the page you saw that on?

According to
<http://www-128.ibm.com/developerworks/java/library/j-jtp03304/>

"The original semantics for volatile guaranteed only that reads and writes of
volatile fields would be made directly to main memory, instead of to registers
or the local processor cache, ... In other words, this means that the old
memory model made promises only about the visibility of the variable being
read or written, and no promises about the visibility of writes to other
variables. While this was easier to implement efficiently, it turned out to be
less useful than initially thought.
"...
"The JSR 133 Expert Group decided that it would be more sensible for volatile
reads and writes not to be reorderable with any other memory operations ...
Under the new memory model, when thread A writes to a volatile variable V, and
thread B reads from V, any variable values that were visible to A at the time
that V was written are guaranteed now to be visible to B."

So it seems that what used to be is now better.

- Lew
 
E

Eric Sosman

Knute said:
Is that not what you get with volatile?

Hmmm... <browses the specifications, scratches head, gets
splinters under fingernails>. Perhaps it is. It seems the
precise meaning of `volatile' has undergone some changes, and
that the memory-ordering semantics are now tighter than they
used to be. (See Lew's post on this thread for an informative
quote.)

mei, my answer is correct (I think) for older Java versions,
but is wrong for the latest versions. I apologize for the
out-of-date information.
 
K

Knute Johnson

Lew said:
According to
<http://www-128.ibm.com/developerworks/java/library/j-jtp03304/>

"The original semantics for volatile guaranteed only that reads and
writes of volatile fields would be made directly to main memory, instead
of to registers or the local processor cache, ... In other words, this
means that the old memory model made promises only about the visibility
of the variable being read or written, and no promises about the
visibility of writes to other variables. While this was easier to
implement efficiently, it turned out to be less useful than initially
thought.
"...
"The JSR 133 Expert Group decided that it would be more sensible for
volatile reads and writes not to be reorderable with any other memory
operations ... Under the new memory model, when thread A writes to a
volatile variable V, and thread B reads from V, any variable values that
were visible to A at the time that V was written are guaranteed now to
be visible to B."

So it seems that what used to be is now better.

- Lew

Lew:

That's an excellent article, thanks for finding that.
 
K

Knute Johnson

Eric said:
Hmmm... <browses the specifications, scratches head, gets
splinters under fingernails>. Perhaps it is. It seems the
precise meaning of `volatile' has undergone some changes, and
that the memory-ordering semantics are now tighter than they
used to be. (See Lew's post on this thread for an informative
quote.)

mei, my answer is correct (I think) for older Java versions,
but is wrong for the latest versions. I apologize for the
out-of-date information.

Thanks Eric.
 
C

Chris Uppal

Lew said:
According to
<http://www-128.ibm.com/developerworks/java/library/j-jtp03304/> [...]
"The JSR 133 Expert Group decided that it would be more sensible for
volatile reads and writes not to be reorderable with any other memory
operations ... Under the new memory model, when thread A writes to a
volatile variable V, and thread B reads from V, any variable values that
were visible to A at the time that V was written are guaranteed now to be
visible to B."

Can anyone point me to the passages in JLS3 which imply that. My own study of
the new stuff has been patchy (and reluctant), but I haven't yet seen anything
to make the following wrong. (I'm not claiming it /isn't/ wrong, only asking
for corroboration, or -- better -- refutation).

With the above caveat. Given a non-local volatile variable:

volatile int[] volatileField;

It seems to me that if one thread does the following:

int[] local = new array[2];
local[0] = 100;
local[1] = 200;
volatileField = local;

then there are only so many things that another thread, subsequently reading
the volatileField's contents, is guaranteed to see.

I believe the following to be guaranteed:

volatileField is not null.
volatileField refers to an int[] array of length 2.
volatileField[0] is either 0 or 100
volatileField[1] is either 0 or 200

However, I haven't yet found anything to convince me that any of the following
are illegal:

volatileField[0] == 0 && volatileField[1] == 0
volatileField[0] == 100 && volatileField[1] == 0
volatileField[0] == 0 && volatileField[1] == 200
volatileField[0] == 100 && volatileField[1] == 200

The wording in JLS3 seems to be quite specific about the happens
before-relationship[*] as it applies to volatiles, and it only seems to refer
to the value of the volatile /itself/, not to any other actions.

It may be that the later stuff (causality, etc) in the JLS3 clears this up, but
as far at the HB relation goes, I can't see that the visible contents of the
array are fully constrained.

-- chris

[*] which I think would be better named: must-not-be-seen-to-happen-after.
 
M

mei

Knute Johnson a écrit :
I looked and couldn't find the reference you mentioned. Do you have the
URL of the page you saw that on?

Thanks,

Here it is even though it seems it is outdated:
http://java.sun.com/docs/books/tutorial/essential/concurrency/atomic.html
"Atomic actions cannot be interleaved, so they can be used without fear
of thread interference. However, this does not eliminate all need to
synchronize atomic actions, because memory consistency errors are still
possible."
 
M

mei

Lew a écrit :
They are talking about "happens-before" relationships.

- Lew

Ok, you are right: As far as I understand it, what the Sun tutorial
explains about the happens-before relationship matches with what is said
in the IBM article. Thus the tutorial is also up-to-date.
But still the tutorial claims that this new semantic of volatile is not
enough to prevent from memory consistency errors. So I think my initial
question is still unanswered, or am I missing something?
 
L

Lew

mei said:
As far as I understand it, what the Sun tutorial
explains about the happens-before relationship matches with what is said
in the IBM article. Thus the tutorial is also up-to-date.
But still the tutorial claims that this new semantic of volatile is not
enough to prevent from memory consistency errors. So I think my initial
question is still unanswered, or am I missing something?

See Chris Uppal's answer in this thread. It includes an example of what might
be inconsistent.

- Lew
 
K

Knute Johnson

Chris said:
Lew said:
According to
<http://www-128.ibm.com/developerworks/java/library/j-jtp03304/> [...]
"The JSR 133 Expert Group decided that it would be more sensible for
volatile reads and writes not to be reorderable with any other memory
operations ... Under the new memory model, when thread A writes to a
volatile variable V, and thread B reads from V, any variable values that
were visible to A at the time that V was written are guaranteed now to be
visible to B."

Can anyone point me to the passages in JLS3 which imply that. My own study of
the new stuff has been patchy (and reluctant), but I haven't yet seen anything
to make the following wrong. (I'm not claiming it /isn't/ wrong, only asking
for corroboration, or -- better -- refutation).

With the above caveat. Given a non-local volatile variable:

volatile int[] volatileField;

It seems to me that if one thread does the following:

int[] local = new array[2];
local[0] = 100;
local[1] = 200;
volatileField = local;

then there are only so many things that another thread, subsequently reading
the volatileField's contents, is guaranteed to see.

I believe the following to be guaranteed:

volatileField is not null.
volatileField refers to an int[] array of length 2.
volatileField[0] is either 0 or 100
volatileField[1] is either 0 or 200

However, I haven't yet found anything to convince me that any of the following
are illegal:

volatileField[0] == 0 && volatileField[1] == 0
volatileField[0] == 100 && volatileField[1] == 0
volatileField[0] == 0 && volatileField[1] == 200
volatileField[0] == 100 && volatileField[1] == 200

The wording in JLS3 seems to be quite specific about the happens
before-relationship[*] as it applies to volatiles, and it only seems to refer
to the value of the volatile /itself/, not to any other actions.

It may be that the later stuff (causality, etc) in the JLS3 clears this up, but
as far at the HB relation goes, I can't see that the visible contents of the
array are fully constrained.

-- chris

[*] which I think would be better named: must-not-be-seen-to-happen-after.

I think if you look at this situation as class with two int fields
rather than an int[] you will see that the fields are not volatile
unless declared so. So while the variable volatileField would indeed
reference the correct int[] there would be no synchronization of the
array elements across threads.

Or at least that is what I think today :). Then again it could all be
different with arrays.
 
K

Knute Johnson

Knute said:
Chris said:
Lew said:
According to
<http://www-128.ibm.com/developerworks/java/library/j-jtp03304/> [...]
"The JSR 133 Expert Group decided that it would be more sensible for
volatile reads and writes not to be reorderable with any other memory
operations ... Under the new memory model, when thread A writes to a
volatile variable V, and thread B reads from V, any variable values that
were visible to A at the time that V was written are guaranteed now
to be
visible to B."

Can anyone point me to the passages in JLS3 which imply that. My own
study of
the new stuff has been patchy (and reluctant), but I haven't yet seen
anything
to make the following wrong. (I'm not claiming it /isn't/ wrong, only
asking
for corroboration, or -- better -- refutation).

With the above caveat. Given a non-local volatile variable:

volatile int[] volatileField;

It seems to me that if one thread does the following:

int[] local = new array[2];
local[0] = 100;
local[1] = 200;
volatileField = local;

then there are only so many things that another thread, subsequently
reading
the volatileField's contents, is guaranteed to see.

I believe the following to be guaranteed:

volatileField is not null.
volatileField refers to an int[] array of length 2.
volatileField[0] is either 0 or 100
volatileField[1] is either 0 or 200

However, I haven't yet found anything to convince me that any of the
following
are illegal:

volatileField[0] == 0 && volatileField[1] == 0
volatileField[0] == 100 && volatileField[1] == 0
volatileField[0] == 0 && volatileField[1] == 200
volatileField[0] == 100 && volatileField[1] == 200

The wording in JLS3 seems to be quite specific about the happens
before-relationship[*] as it applies to volatiles, and it only seems
to refer
to the value of the volatile /itself/, not to any other actions.

It may be that the later stuff (causality, etc) in the JLS3 clears
this up, but
as far at the HB relation goes, I can't see that the visible contents
of the
array are fully constrained.

-- chris

[*] which I think would be better named:
must-not-be-seen-to-happen-after.

I think if you look at this situation as class with two int fields
rather than an int[] you will see that the fields are not volatile
unless declared so. So while the variable volatileField would indeed
reference the correct int[] there would be no synchronization of the
array elements across threads.

Or at least that is what I think today :). Then again it could all be
different with arrays.

And I found some more interesting things. Look at AtomicBoolean in the
docs and follow the link 'java.util.concurrent.atomic'. It has a
discussion of the Atomic??? classes and especially see
AtomicIntegerArray. I still think that it would require synchronization
to prevent memory consistency errors however.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top