title: c++ multithread atomic load/store
body: <p>When I read the 5th chapter of the book <a href="https://www.bogotobogo.com/cplusplus/files/CplusplusConcurrencyInAction_PracticalMultithreading.pdf" rel="nofollow noreferrer">CplusplusConcurrencyInAction</a>, the example code as follows, multithread load/store some atomic values concurrently with the momery_order_relaxed.Three array save the value of <code>x、y and z</code> respectively at each round.</p>
  
  <pre><code>#include &lt;thread&gt;
  #include &lt;atomic&gt;
  #include &lt;iostream&gt;
  ​
  std::atomic&lt;int&gt; x(0),y(0),z(0);  // 1
  std::atomic&lt;bool&gt; go(false);  // 2
  ​
  unsigned const loop_count=10;
  ​
  struct read_values
  {
    int x,y,z;
  };
  ​
  read_values values1[loop_count];
  read_values values2[loop_count];
  read_values values3[loop_count];
  read_values values4[loop_count];
  read_values values5[loop_count];
  ​
  void increment(std::atomic&lt;int&gt;* var_to_inc,read_values* values)
  {
    while(!go)
      std::this_thread::yield();  
    for(unsigned i=0;i&lt;loop_count;++i)
    {
      values[i].x=x.load(std::memory_order_relaxed);
      values[i].y=y.load(std::memory_order_relaxed);
      values[i].z=z.load(std::memory_order_relaxed);
      var_to_inc-&gt;store(i+1,std::memory_order_relaxed);  // 4
      std::this_thread::yield();
    }
  }
  ​
  void read_vals(read_values* values)
  {
    while(!go)
      std::this_thread::yield(); 
    for(unsigned i=0;i&lt;loop_count;++i)
    {
      values[i].x=x.load(std::memory_order_relaxed);
      values[i].y=y.load(std::memory_order_relaxed);
      values[i].z=z.load(std::memory_order_relaxed);
      std::this_thread::yield();
    }
  }
  ​
  void print(read_values* v)
  {
    for(unsigned i=0;i&lt;loop_count;++i)
    {
      if(i)
        std::cout&lt;&lt;",";
      std::cout&lt;&lt;"("&lt;&lt;v[i].x&lt;&lt;","&lt;&lt;v[i].y&lt;&lt;","&lt;&lt;v[i].z&lt;&lt;")";
    }
    std::cout&lt;&lt;std::endl;
  }
  ​
  int main()
  {
    std::thread t1(increment,&amp;x,values1);
    std::thread t2(increment,&amp;y,values2);
    std::thread t3(increment,&amp;z,values3);
    std::thread t4(read_vals,values4);
    std::thread t5(read_vals,values5);
  ​
    go=true;  
  ​
    t5.join();
    t4.join();
    t3.join();
    t2.join();
    t1.join();
  ​
    print(values1);  
    print(values2);
    print(values3);
    print(values4);
    print(values5);
  }
  </code></pre>
  
  <p>one of the valid output mentioned in this chapter:</p>
  
  <pre><code>(0,0,0),(1,0,0),(2,0,0),(3,0,0),(4,0,0),(5,7,0),(6,7,8),(7,9,8),(8,9,8),(9,9,10)
  (0,0,0),(0,1,0),(0,2,0),(1,3,5),(8,4,5),(8,5,5),(8,6,6),(8,7,9),(10,8,9),(10,9,10)
  (0,0,0),(0,0,1),(0,0,2),(0,0,3),(0,0,4),(0,0,5),(0,0,6),(0,0,7),(0,0,8),(0,0,9)
  (1,3,0),(2,3,0),(2,4,1),(3,6,4),(3,9,5),(5,10,6),(5,10,8),(5,10,10),(9,10,10),(10,10,10)
  (0,0,0),(0,0,0),(0,0,0),(6,3,7),(6,5,7),(7,7,7),(7,8,7),(8,8,7),(8,8,9),(8,8,9)
  </code></pre>
  
  <p>The 3rd output of <code>values1</code> is <code>(2,0,0)</code>,at this point it reads <code>x=2</code>,and <code>y=z=0</code>.It means when <code>y=0</code>,the <code>x</code> is already equals to 2, Why the 3rd output of the <code>values2</code> it reads <code>x=0</code> and <code>y=2</code>,which means x is the old value because <code>x、y、z</code> is increasing, so when <code>y=2</code> that x is at least 2. 
  And I test the code in my PC,I can't reproduce the result like that.</p>