\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}