5

Consider a simple, single-threaded Java program execution involving no synchronization actions, just plain reads and writes of instance variables. An implementation that simply ignores all writes seems to comply with the Java Memory Specification. First, the applicable general statement from §17.4:

The memory model determines what values can be read at every point in the program. The actions of each thread in isolation must behave as governed by the semantics of that thread, with the exception that the values seen by each read are determined by the memory model.

The relevant constraints would be the following (§17.4.5):

1. happens-before ordering induced by program order:

If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).

2. happens-before consistency:

A set of actions A is happens-before consistent if for all reads r in A, where W(r) is the write action seen by r, it is not the case that either hb(r, W(r)) or that there exists a write w in A such that w.v = r.v and hb(W(r), w) and hb(w, r).

This basically precludes a read happening-before the write it observes. The other provision is just a sanity clause that prevents a read of some v seeing an earlier write of that v that was in the meantime followed by another write of the same v.

I cannot find any guarantee whatsoever that a write will positively be observed, only restrictions on what writes may not be observed.

What am I missing here? Is it really possible that the JVM leaves out such a trivial guarantee?

Community
  • 1
  • 1
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • 2
    I am not sure what guarantee you feel is missing. Can you give an example of where this could cause a problem? A write will not be observed if, a) its not read b) its over-written before reading. Its what you read which matters. – Peter Lawrey Aug 29 '12 at 09:58
  • A simple `this.i = 3; System.out.println(this.i);` is not guaranteed to print 3. It could print 0 (the initial value, I guess this is the only one guaranteed to be there). – Marko Topolnik Aug 29 '12 at 09:59
  • 4
    I can feel the headache coming, followed by the confusion, then the astonishement: I need a coke... – assylias Aug 29 '12 at 10:01
  • 1
    The memory model assumes single threads will behave as you would expect. `The actions of each thread in isolation must behave as governed by the semantics of that thread,` Its only multiple threads where the memory model has anything interesting to say. – Peter Lawrey Aug 29 '12 at 10:01
  • @PeterLawrey Notice the **exception** part :) *with the exception that the values seen by each read are determined by the memory model.* – Marko Topolnik Aug 29 '12 at 10:01
  • 2
    @assylias Did you know that Coca-cola got its name from the fact it had cocaine in it. It was replaced with caffeine when cocaine became illegal. ;) – Peter Lawrey Aug 29 '12 at 10:02
  • @PeterLawrey I really think you meant *had*, because if it still *has*.. :) – Eugene Aug 29 '12 at 10:03
  • @MarkoTopolnik Ok `If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).` – Peter Lawrey Aug 29 '12 at 10:04
  • @PeterLawrey I'm following... the write definitely *happens-before* the read. Now what? Where's the guarantee that the read will observe that particular write? – Marko Topolnik Aug 29 '12 at 10:05

1 Answers1

4

Let's use:

class MyClass {
    private static int i = 0;

    public static void main(String[] args) {
        i = 3; //w
        System.out.println(i); //r
    }
}
  • A program is correctly synchronized if and only if all sequentially consistent executions are free of data races.
  • If a program is correctly synchronized, then all executions of the program will appear to be sequentially consistent (§17.4.3).
  • When a program contains two conflicting accesses (§17.4.1) that are not ordered by a happens-before relationship, it is said to contain a data race.

    Your program is single threaded
    => we have hb(w,r) from the program order constraint
    => it is correctly synchronized
    => all executions of the program will appear to be sequentially consistent.
    => it will print 3

assylias
  • 321,522
  • 82
  • 660
  • 783
  • 2
    @MarkoTopolnik You are giving up easily today ;-) – assylias Aug 29 '12 at 10:14
  • 2
    Yes, quite a change from the last time... what can I say, this sounds right, feels right, and after staring at it for several minutes (and including all the staring at JLS done in the last two weeks), I think this argument is impeccable. I missed that connection to "appearing to be sequentially consistent", which on its own brings in hard guarantees. – Marko Topolnik Aug 29 '12 at 10:15
  • BTW regarding my previous question, I found even more fishiness when reading the doc on `lazySet`. It specifies an action fully compatible with the definition of a volatile write, but says "unlike volatile, timeliness not guaranteed" (words to that effect). From that it would follow that timeliness is guaranteed somewhere for a volatile write, but isn't. It's a strange unwritten, tacit assumption by everyone. – Marko Topolnik Aug 29 '12 at 10:18
  • 1
    @MarkoTopolnik thank you for the question. For a user in the non k-ish points, if this would have brought any *doubt* in the hb relationship on a single threaded issue, I would be really amazed for a long time – Eugene Aug 29 '12 at 10:22