Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory Consistency - happens-before relationship in Java [duplicate]

While reading Java docs on Memory Consistency errors. I find points related to two actions that creates happen - before relationship:

  • When a statement invokes Thread.start(), every statement that has a happens-before relationship with that statement also has a happens-before relationship with every statement executed by the new thread. The effects of the code that led up to the creation of the new thread are visible to the new thread.

  • When a thread terminates and causes a Thread.join() in another thread to return, then all the statements executed by the terminated
    thread have a happens-before relationship with all the statements
    following the successful join. The effects of the code in the thread are now visible to the thread that performed the join.

I am not able to understand their meaning. It would be great if someone explain it with a simple example.

like image 865
Prateek Avatar asked Apr 27 '13 06:04

Prateek


People also ask

What is happens before relationship in Java?

If one action 'x' is visible to and ordered before another action 'y', then there is a happens-before relationship between the two actions indicated by hb(x, y). If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).

What is memory consistency in Java?

When the concept of multithreading is implemented, it is possible that changes made by one thread wouldn't be visible to the other thread. This indicates that the view of each thread is inconsistent with respect to each other. This is known as memory consistency error.

What is memory consistency errors?

Memory consistency errors occur when different threads have inconsistent views of what should be the same data. The causes of memory consistency errors are complex and beyond the scope of this tutorial. Fortunately, the programmer does not need a detailed understanding of these causes.

How does Java memory model work?

Java memory model is divided between Thread Stacks (One for each thread) and a heap area. Thread Stack: It is a thread specific memory area and contains local variables, methods call information etc. JVM stacks could be of fixed size or variable size.


2 Answers

Modern CPUs don't always write data to memory in the order it was updated, for example if you run the pseudo code (assuming variables are always stored to memory here for simplicity);

a = 1 b = a + 1 

...the CPU may very well write b to memory before it writes a to memory. This isn't really a problem as long as you run things in a single thread, since the thread running the code above will never see the old value of either variable once the assignments have been made.

Multi threading is another matter, you'd think the following code would let another thread pick up the value of your heavy computation;

a = heavy_computation() b = DONE 

...the other thread doing...

repeat while b != DONE     nothing  result = a 

The problem though is that the done flag may be set in memory before the result is stored to memory, so the other thread may pick up the value of memory address a before the computation result is written to memory.

The same problem would - if Thread.start and Thread.join didn't have a "happens before" guarantee - give you problems with code like;

a = 1 Thread.start newthread ...  newthread:     do_computation(a) 

...since a may not have a value stored to memory when the thread starts.

Since you almost always want the new thread to be able to use data you initialized before starting it, Thread.start has a "happens before" guarantee, that is, data that has been updated before calling Thread.start is guaranteed to be available to the new thread. The same thing goes for Thread.join where data written by the new thread is guaranteed to be visible to the thread that joins it after termination.

It just makes threading much easier.

like image 160
Joachim Isaksson Avatar answered Oct 22 '22 10:10

Joachim Isaksson


Consider this:

static int x = 0;  public static void main(String[] args) {     x = 1;     Thread t = new Thread() {         public void run() {             int y = x;         };     };     t.start(); } 

The main thread has changed field x. Java memory model does not guarantee that this change will be visible to other threads if they are not synchronized with the main thread. But thread t will see this change because the main thread called t.start() and JLS guarantees that calling t.start() makes the change to x visible in t.run() so y is guaranteed to be assigned 1.

The same concerns Thread.join();

like image 24
Evgeniy Dorofeev Avatar answered Oct 22 '22 10:10

Evgeniy Dorofeev