From: Roedy Green on 12 Feb 2010 10:23 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 12 Feb 2010 11:12 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 12 Feb 2010 11:34 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 12 Feb 2010 11:36 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 12 Feb 2010 11:46
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/ |