Home > Back-end >  Java Memory Model - Surprising Behaviors
Java Memory Model - Surprising Behaviors

Time:10-11

I am reading about Java Memory Model in JSR-133 and I cannot understand how this type of behavior is acceptable:
enter image description here

Can somebody please explain it?

CodePudding user response:

8.1 Surprising Behaviors Allowed by the Memory Model

Figure 12 shows a small but interesting example. The behavior r1 == 2 and r2 == 1 is a legal behavior, although it may be difficult to see how it could occur. A compiler would not reorder the statements in each thread; this code must never result in r1 == 1 or r2 == 2. However, the behavior r1 == 2 and r2 == 1 might be allowed by a processor architecture that performs the writes early, but in a way that they were not visible to local reads that came before them in program order. This behavior, while surprising, is allowed by the Java memory model. To get this result in the memory model, we commit both writes followed by both reads.

Somehow the CPU has decided to write x earlier than to read x. All what this example says is, that this is valid behavior, more or less, this is an exception which is accepted as valid behavior.

Intel Itanium CPU could produce such behavior.

So instead of:

//Thread 1
int x = 0;
int r1 = x;
x = 1;

//Thread 2
int x = 0;
int r2 = x;
x = 2;

This happens:

//Thread 1
int x = 0;
x = 2; //from Thread 2
int r1 = x;

//Thread 2
int x = 0;
x = 1; //from Thread 1
int r2 = x;

And this is totally valid. (An accepted exception.)

CodePudding user response:

The ONLY thing the CPU has to ensure is that the write to X within a thread does NOT affect the subsequent assignment to its associated RX memory location. It says nothing about where it gets the value it's going to write from.

So, In thread 1, the CPU says
"Ohh, I need to read X", so begins a read operation.
It then says
"And I need to write to X", so then QUEUES the value in a write queue

Thread 2 does the same thing.
"Ohh, I need to read X" and begins the read.
"I need to write to X", and queues the write.

Now we have two waiting reads and two queued writes.

If the CPU architecture says that a read on one core may interrogate another core's write queue, then both cores can read each others outstanding writes to X. Hence you get the two values being pulled across cores, ultimately being assigned to the RX memory location from that thread.

When you place memory barriers in the instruction stream it prevents this type of over eager queued write reading.

  • Related