C++11之原子操作原理与使用

1、 原子操作:std::atomic

【1】原子操作理解为:不需要用到互斥量加锁(无锁)技术的多线程并发编程方式,并且原子操作在多线程中不会被打断执行;        
【2】原子操作比互斥量在效率上更高;
【3】互斥量的加锁一般是针对一个代码段(几行代码), 原子操作针对的都是一个变量,而不是针对一个代码段;

【4】原子操作:该变量要么完成,要么没完成,不存在中间状态
   std::atomic代表原子操作。std::atomic是一个类模板,用于封装某个类型的值;

2.原子操作步骤(分三步:Read ---> Modified ----> Write)

atomic是原子的意思,意味"不可分割"的整体。在Linux kernel中有一类atomic操作API。这些操作对用户而言是原子执行的,在一个CPU上执行过程中,不会被其他CPU打断。最常见的操作是原子读改写,简称RMW。

【1】单个CPU的情况

一个变量自增操作,CPU微观指令级别分成3步操作。

1) 先read变量的值到CPU内存寄存器; //读:Read

2) 对寄存器的值递增;//改:Modified

3) 将寄存器的值写回变量。//写: Write


 3.多线程访问一个变量例子

【1】有两个线程,线程thread1对变量aa读操作,线程thread2对变量中写值。

int aa = 5;

【2】在线程thread1里,对aa读操作,放入tmp变量中,以后使用

int tmp = aa ;//aa代表的是多个线程之间要共享的变量

【3】在线程thread2里,对aa写操作

aa = 100;

结果:原本是想读出来aa = 5的值,结果可能读出来是已经修改的值100,不是自己想要的脏数据,所以对变量读写要保持其原子性----->即:执行中不可被打断。

原子操作:
可以把原子操作理解为:不需要用到互斥量加锁(无锁)技术的多线程编程方式,多线程中不会被打断的程序执行片段。
 

4.原子操作测试demo

#include <thread>
#include <atomic>
#include <iostream>
using namespace std;
//1.have atomic
//atomic<int> g_count;

//2.no atomic
int g_count = 0;

void work(){
  for (int i = 0;i < 100000;i++){
    g_count++;
  }
  return;
}

int main(){
  std::thread t1(work);
  std::thread t2(work);
  t1.join();
  t2.join();

  //如果没有使用atomic原子定义,打印的值是随机,是乱的
  cout << "g_count =  " << g_count << endl;
}

总结:

1.先理解下CPU和内存连接方式

在SMP系统中,多个CPU通过共享的总线和内存相连接,如果它们同时申请访问内存,那么总线就会从硬件上进行仲裁,以确定接下来哪一个CPU可以使用总线,然后将总线授权给它,并且允许该CPU完成一次原子的load操作或者store操作。在完成每一次操作之后,就会重复这个周期:对总线进行仲裁,并授权给另一个CPU。每次只能有一个CPU使用总线

2.理解原子操作

原子操作常用的做法是给总线上锁(bus lock),以获得在一定的时间窗口内对总线独占的授权,就好像是一个CPU在告诉总线说“在我完成之前,别让其他CPU来读写内存的数据”。

猜你喜欢

转载自blog.csdn.net/u010164190/article/details/125157771