From: Roedy Green on
Originally I thought volatile just suppressed caching a value in a
register, so that other threads going to RAM would see the latest
value.

IIRC at least in some early JVM, you could not count on 64-bit loads
and stores being atomic.

But on reading the JLS, it seems to guarantee even more. It says all
threads must see a consistent value.

This suggests if your hardware stores a 64-bit long in two 32-bit
stores, it must somehow lock the pair together so that another thread
will not see half the store. I wonder just how they do that, and if
they indeed do.

I don't think the JLS guarantees that a volatile x++ must be atomic.
It appears to be silent on the topic, which I take to mean you can't
count on it.

Any thoughts?
--
Roedy Green Canadian Mind Products
http://mindprod.com

Every compilable program in a sense works. The problem is with your unrealistic expections on what it will do.
From: Roedy Green on
On Fri, 12 Feb 2010 07:23:13 -0800, Roedy Green
<see_website(a)mindprod.com.invalid> wrote, quoted or indirectly quoted
someone who said :

>
>I don't think the JLS guarantees that a volatile x++ must be atomic.
>It appears to be silent on the topic, which I take to mean you can't
>count on it.

Using javap, a volatile long++ looks like this:

0: getstatic #2; //Field key:J
3: lconst_1
4: ladd
5: putstatic #2; //Field key:J

This implies there is no guarantee of atomicity for ++.
--
Roedy Green Canadian Mind Products
http://mindprod.com

Every compilable program in a sense works. The problem is with your unrealistic expections on what it will do.
From: Andreas Leitgeb on
Roedy Green <see_website(a)mindprod.com.invalid> wrote:
> On Fri, 12 Feb 2010 07:23:13 -0800, Roedy Green wrote (all himself):
>> I don't think the JLS guarantees that a volatile x++ must be atomic.
>> It appears to be silent on the topic, which I take to mean you can't
>> count on it.

No, x++ is indeed *not* guaranteed to be atomic for any "++"-able type.

See AtomicInteger and friends for alternatives (if synchronized not wanted).

but volatile helps in another case:
volatile long x;
thread 1 thread 2
x=0xffffffff;
x=0x100000000L; (x==0xffffffff) || (x==0x100000000L) is true:

/*non-volatile*/ long y;
thread 1 thread 2
y=0xffffffff;
y=0x100000000L; y could also look like 0 or 0x1ffffffffL !!!

From: Eric Sosman on
On 2/12/2010 10:23 AM, Roedy Green wrote:
> Originally I thought volatile just suppressed caching a value in a
> register, so that other threads going to RAM would see the latest
> value.
>
> IIRC at least in some early JVM, you could not count on 64-bit loads
> and stores being atomic.
>
> But on reading the JLS, it seems to guarantee even more. It says all
> threads must see a consistent value.
>
> This suggests if your hardware stores a 64-bit long in two 32-bit
> stores, it must somehow lock the pair together so that another thread
> will not see half the store. I wonder just how they do that, and if
> they indeed do.
>
> I don't think the JLS guarantees that a volatile x++ must be atomic.
> It appears to be silent on the topic, which I take to mean you can't
> count on it.

"Consistent value" is what you're promised, and it's up to
the JVM to deliver it by doing whatever is required.

Your recollection about 64-bit accesses is correct, but it's
a remembrance of things past: Early Java allowed non-atomicity as
a concession to machines that lacked 64-bit atomic operations.
But 64-bit-capable machines are now the norm instead of the
exception, and the rules have been tightened up. (I think this
may have happened as part of the effort to nail down Java's memory
model, which was pretty loosey-goosey in the early days.)

There's no atomicity guarantee for things like x++ or x+=42,
because these are not single accesses: They need paired reads
and writes. The read will be atomic and fetch a consistent
value, the write will be atomic and store a consistent value,
but other (individually atomic) reads and writes may intervene.

Before anybody whines^H^H^H^H^H^Hsuggests that making +=
atomic would be easy, let him ponder

volatile int a,b,c,...,z;
a += b += c+= ... += z;

--
Eric Sosman
esosman(a)ieee-dot-org.invalid
From: Knute Johnson on
On 2/12/2010 7:23 AM, Roedy Green wrote:
> Originally I thought volatile just suppressed caching a value in a
> register, so that other threads going to RAM would see the latest
> value.
>
> IIRC at least in some early JVM, you could not count on 64-bit loads
> and stores being atomic.
>
> But on reading the JLS, it seems to guarantee even more. It says all
> threads must see a consistent value.
>
> This suggests if your hardware stores a 64-bit long in two 32-bit
> stores, it must somehow lock the pair together so that another thread
> will not see half the store. I wonder just how they do that, and if
> they indeed do.
>
> I don't think the JLS guarantees that a volatile x++ must be atomic.
> It appears to be silent on the topic, which I take to mean you can't
> count on it.
>
> Any thoughts?

From Java Concurrency in Practice by Goetz, "For example the semantics
of volatile are not strong enough to make the increment operation (x++)
atomic, unless you can guarantee that the variable is written only from
a single thread."

The other, and I think most important side effect of volatile is, "The
visibility effects of volatile variables extend beyond the value of the
volatile variable itself. When thread A writes to a volatile variable
and subsequently thread B reads that same variable, the values of ALL
variables that were visible to A prior to writing to the volatile
variable become visible to B after reading the volatile variable" again
from Java Concurrency in Practice.

--

Knute Johnson
email s/nospam/knute2010/