下面从一个问题引入:

// ConsoleApplication5.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include<random>
#include<iostream>
#include<vector>
#include<thread>
#include<algorithm>
#include<future>
using namespace std;
int x = 0;
void mythread_one()
{
for (int i = 1; i < 1000000; i++)
{
x++;
}
} void mythread_two()
{
for (int i = 0; i < 1000000; i++)
{
x++;
}
}
int main()
{ thread th_one(mythread_one);
thread th_two(mythread_two);
th_one.join();
th_two.join(); cout << "x的值为:" << x << endl; return 0;
}

执行结果:

这段程序设置了两个线程,然后对全局变量进行加加操作,但是执行的结果却不是我们真正想要的。

解决办法可以对访问的数据加锁:

// ConsoleApplication5.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include<random>
#include<iostream>
#include<vector>
#include<thread>
#include<algorithm>
#include<future>
using namespace std;
int x = 0;
mutex g;
void mythread_one()
{
for (int i = 1; i < 10000000; i++)
{
g.lock();
x++;
g.unlock();
}
} void mythread_two()
{
for (int i = 0; i < 10000000; i++)
{
g.lock();
x++;
g.unlock();
}
}
int main()
{ thread th_one(mythread_one);
thread th_two(mythread_two);
th_one.join();
th_two.join(); cout << "x的值为:" << x << endl; return 0;
}

这样的确可以解决问题,但是为了提升效率,C++11引入了原子操作atomic<>,它能够保证在读取数据的时候不会被打断,和加锁机制相比,他的效率更高.

代码演示:

// ConsoleApplication5.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include<random>
#include<iostream>
#include<vector>
#include<thread>
#include<algorithm>
#include<future>
using namespace std;
int x = 0;
atomic<int> g = 0;
void mythread_one()
{
for (int i = 1; i < 10000000; i++)
{
g++;
}
} void mythread_two()
{
for (int i = 0; i < 10000000; i++)
{
g++;
}
}
int main()
{ thread th_one(mythread_one);
thread th_two(mythread_two);
th_one.join();
th_two.join(); cout << "x的值为:" << x << endl; return 0;
}

接下来再看另一个原子操作atomic<bool> ,他用于终止线程的执行:

// ConsoleApplication5.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include<random>
#include<iostream>
#include<vector>
#include<thread>
#include<algorithm>
#include<future>
using namespace std;
int x = 0;
atomic<bool> g_ifend=false;
void mythread()
{
cout << "子线程1开始执行了" << endl;
while (g_ifend == false)
{
cout << "任务执行中..." << endl;
this_thread::sleep_for(chrono::seconds(2));
}
cout << "子线程任务执行结束" << endl;
} int main()
{ cout << "主线程开始执行了" << endl;
thread th(mythread);
this_thread::sleep_for(chrono::seconds(5));
g_ifend = true;//让主线程等待5秒,过了5秒,让子线程结束任务
th.join();
cout << "主线程执行任务结束了" << endl; return 0;
}

原子操作atomic解读的更多相关文章

  1. 并发编程之原子操作Atomic&Unsafe

    原子操作:不能被分割(中断)的一个或一系列操作叫原子操作. 原子操作Atomic主要有12个类,4种类型的原子更新方式,原子更新基本类型,原子更新数组,原子更新字段,原子更新引用.Atomic包中的类 ...

  2. java并发:线程同步机制之Volatile关键字&原子操作Atomic

    volatile关键字 volatile是一个特殊的修饰符,只有成员变量才能使用它,与Synchronized及ReentrantLock等提供的互斥相比,Synchronized保证了Synchro ...

  3. 什么是Java中的原子操作( atomic operations)

    1.啥是java的原子性 原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行. 一个很经典的例子就是银行账户转账问题: 比如从账户A向账户B转1000元,那么 ...

  4. golang中的原子操作atomic包

    1. 概念 原子操作 atomic 包 加锁操作涉及到内核态的上下文切换,比较耗时,代价高, 针对基本数据类型我们还可以使用原子操作来保证并发的安全, 因为原子操作是go语言提供的方法,我们在用户态就 ...

  5. C++11并发编程:原子操作atomic

    一:概述 项目中经常用遇到多线程操作共享数据问题,常用的处理方式是对共享数据进行加锁,如果多线程操作共享变量也同样采用这种方式. 为什么要对共享变量加锁或使用原子操作?如两个线程操作同一变量过程中,一 ...

  6. 原子操作atomic

    一.原子操作:即不可再细分的操作,最小的执行单位,在操作完之前都不会被任何事件中断. 整型原子操作:对int类型的操作变成原子操作.                 int i = 0;       ...

  7. 原子操作(atomic operation)

    深入分析Volatile的实现原理 引言 在多线程并发编程中synchronized和Volatile都扮演着重要的角色,Volatile是轻量级的synchronized,它在多处理器开发中保证了共 ...

  8. 【C# 线程】 atomic action原子操作|primitive(基元、原语)

    概念 原子操作(atomic action):也叫primitive(原语.基元),它是操作系统用语范畴.指由若干条指令组成的,用于完成一定功能的一个过程.  原语是由若干个机器指令构成的完成某种特定 ...

  9. Java中的Atomic包

    Atomic包的作用 方便程序员在多线程环境下,无锁的进行原子操作 Atomic包核心 Atomic包里的类基本都是使用Unsafe实现的包装类,核心操作是CAS原子操作: 关于CAS compare ...

随机推荐

  1. IDEA报错 Error:(24, 35) java: 常量字符串过长

    修改设置

  2. 【LeetCode】27. Remove Element 解题报告(Python & Java)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 双指针 记录起始位置 日期 题目地址:https:/ ...

  3. 【LeetCode】150. Evaluate Reverse Polish Notation 解题报告(Python)

    [LeetCode]150. Evaluate Reverse Polish Notation 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/ ...

  4. Kernel PCA and De-Noisingin Feature Spaces

    目录 引 主要内容 Kernel PCA and De-Noisingin Feature Spaces 引 kernel PCA通过\(k(x,y)\)隐式地将样本由输入空间映射到高维空间\(F\) ...

  5. CS5268替代AG9321MCQ 替代AG9321方案 TYPEC转HDMI多功能拓展坞

    台湾安格AG9321MCQ是一款TYPEC拓展坞产品方案,他集中了TYPEC 转HDMI  VGA  PD3.0快充  QC3.0数据传输 I2S接口的音频DAC输出以及可以各种读卡器功能. Caps ...

  6. PHP 中的回调函数

    回调函数就是在主进程执行过程中,满足某个条件后,跳转到预先设置好的函数中去执行的一种函数. 举例说明: 张三到一个水果店买苹果,刚好苹果卖完了,于是张三在店员那里留下了自己的电话,一个小时后店里有货了 ...

  7. CSS基础 定位相关属性的使用方法

    1.相对定位:position:relative: 属性名:position 属性值:relative: 特点:1.相对自己的位置移动 2.配合方位名词移动,如:top.left.right,bott ...

  8. 使用.NET 6开发TodoList应用(22)——实现缓存

    系列导航及源代码 使用.NET 6开发TodoList应用文章索引 需求 有的时候为了减少客户端请求相同资源的逻辑重复执行,我们会考虑使用一些缓存的方式,在.NET 6中,我们可以借助框架提供的中间件 ...

  9. python接口自动化,从excel取param的内容太多,使用eval转换报错'EOL while scanning string literal

    背景: 做接口自动化时,有个接口的参数内容很多,可以从excel中读取出来,但是在eval()进行转化时,就报错"'EOL while scanning string literal&quo ...

  10. 我踩过的python的坑

    1. string中Template用法 变量名不能是${tradeDate+1}, python无法识别其为变量,应改为 ${tradeDate1} 变量替换的语句:data_new = Templ ...