其他线程是否可以立即看到原子操作的副作用?

时间:2018-07-30 02:44:15

标签: multithreading c++11 concurrency memory-barriers

this question中,一位回复者说

  

原子性意味着该操作要么完全执行并且它的所有副作用都可见,要么根本不执行。

但是,下面是并发$ Lising 5.5

中给出的示例
#include <thread>
#include <atomic>
#include <iostream>
std::atomic<int> x(0),y(0),z(0);
std::atomic<bool> go(false);
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<int>* var_to_inc,read_values* values)
{
  while(!go)
  std::this_thread::yield();
  for(unsigned i=0;i<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->store(i+1,std::memory_order_relaxed);
    std::this_thread::yield();
  }
}

void read_vals(read_values* values)
{
  while(!go)
  std::this_thread::yield();
  for(unsigned i=0;i<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<loop_count;++i)
  {
    if(i)
    std::cout<<",";
    std::cout<<"("<<v[i].x<<","<<v[i].y<<","<<v[i].z<<")";
  }
  std::cout<<std::endl;
}
int main()
{
  std::thread t1(increment,&x,values1);
  std::thread t2(increment,&y,values2);
  std::thread t3(increment,&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);
}

作者给出的示例输出是

(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)  

输出似乎表明一个线程中的修改立即对其他线程不可见

作者还说:

  

线程3 看不到x或y的任何更新;它仅看到它的更新   使z。这不会阻止其他线程看到z的更新   混合了x和y的更新。

我很困惑,为什么thread3看不到xy的修改。这是否表示原子操作的副作用是可见的是不正确的?是否遵守由计算机硬件保证的缓存一致性规则?

0 个答案:

没有答案