\pagebreak
\chapter{The OpenMP Memory Model}
\label{chap:mem_model}

In the following example, at Print 1, the value of \plc{x} could be either 2 
or 5, depending on the timing of the threads, and the implementation of the assignment 
to \plc{x}. There are two reasons that the value at Print 1 might not be 5. 
First, Print 1 might be executed before the assignment to \plc{x} is executed. 
Second, even if Print 1 is executed after the assignment, the value 5 is not guaranteed 
to be seen by thread 1 because a flush may not have been executed by thread 0 since 
the assignment.

The barrier after Print 1 contains implicit flushes on all threads, as well as 
a thread synchronization, so the programmer is guaranteed that the value 5 will 
be printed by both Print 2 and Print 3.

\cexample{mem_model}{1c}

\fexample{mem_model}{1f}

The following example demonstrates why synchronization is difficult to perform 
correctly through variables. The value of flag is undefined in both prints on thread 
1 and the value of data is only well-defined in the second print.

\cexample{mem_model}{2c}

\fexample{mem_model}{2f}

The next example demonstrates why synchronization is difficult to perform correctly 
through variables. Because the \plc{write}(1)-\plc{flush}(1)-\plc{flush}(2)-\plc{read}(2) 
sequence cannot be guaranteed in the example, the statements on thread 0 and thread 
1 may execute in either order.

\cexample{mem_model}{3c}

\fexample{mem_model}{3f}


