使用std :: atomic <>进行多线程

时间:2019-07-03 11:05:49

标签: c++ multithreading atomic lock-free

在下面的小代码示例中,我不明白,当线程开始增加计数器时,该线程将在内核之间共享的高速缓存中写入计数器地址,并使计数器锁定在高速缓存中,直到该线程已经完成了在计数器中的写入,但是如果在先前的线程读写修改之间再次尝试向该计数器添加+1,他将看到高速缓存中的数据是锁定的,然后呢?第二个线程会休眠还是只是等到缓存中的计数器变为解锁状态??

如果线程睡眠,我看不到原子数据和互斥量对于小尺寸数据的好处:

// this_thread::yield example
#include <iostream>       // std::cout
#include <thread>         // std::thread, std::this_thread::yield
#include <atomic>         // std::atomic

std::atomic<bool> ready (false);
std::atomic<int> counter (0);

void count1m(int id) {
  while (!ready) {             // wait until main() sets ready...
    std::this_thread::yield();
  }
  for (volatile int i=0; i<10000; ++i) {
        counter +=1;}
}

int main ()
{
  std::thread threads[10];
  std::cout << "race of 10 threads that count to 1 million:\n";
  for (int i=0; i<10; ++i) threads[i]=std::thread(count1m,i);
  ready = true;               // go!
  for (auto& th : threads) th.join();
  std::cout << counter;
}

1 个答案:

答案 0 :(得分:0)

“缓存锁定”只是延迟对MESI无效或共享请求做出响应的核心。

这不是互斥锁,也不是任何东西,这是单个内核可以通过调整其使用现有MESI高速缓存一致性协议的方式来完成的,该协议可确保高速缓存在同一地址上永远不会有冲突的值。其他核心不必了解“锁定”,它们只是看到对共享线路请求的响应有所延迟。 (无论如何,这都没有任何硬性的截止日期或预期的响应时间;它取决于争用以及有多少其他核心也在等待排他性访问以提交他们的存储或RMW的线路。)< / p>

有关详细信息,请参见Can num++ be atomic for 'int num'?。 (可以说不是重复的,因为那是从更广阔的前提开始的,涵盖了许多与此处无关的内容。)

C ++内存模型假定具有一致的共享内存,这实际上是所有多核计算机所拥有的。始终(AFAIK)使用MESI缓存一致性协议的某些变体。


  

第二个线程会休眠吗?

否,这全在硬件级别上。操作系统不知道核心停滞了,等待缓存行。

这与常规的高速缓存未命中非常相似,它等待数据从DRAM而不是从另一个内核到达。