下面从一个问题引入:

// 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. MAMP的使用

    MAMP下载并安装 下载地址:https://pan.baidu.com/s/1TgoKBG3F59NGO8lEj9mf4Q 密码:2m3d 安装:按照提示,一直下一步直到完成 MAMP操作

  2. DevOps实战(Docker+Jenkins+Git)

    基于Docker+Jenkins+Git的CI/CD实战 与上一篇随笔:基于 Jenkins+Docker+Git 的CI流程初探 有所不同,该内容更偏向于实际业务的基础需求. 有几点需要注意: 该实 ...

  3. C库函数将字符串转大小写

    头文件 #include <algorithm> transform 函数 转大写 std::string str_write; // 全部转为大写 std::transform(str_ ...

  4. Linux c++编译总结(持续更新)

    1. 没有定义的符号 这类的错误, 解决办法:A. 添加对应的头文件(源文件), B.前置声明 1.1 错误描述: error: variable has incomplete type 'class ...

  5. 一个c++11自定义的信号量

    1.关于 This is from here But I did some changes. 2. semaphore.h /** @ brief : this is from https://sta ...

  6. 【LeetCode】945. Minimum Increment to Make Array Unique 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力求解,TLE 一次遍历 日期 题目地址:http ...

  7. 【LeetCode】467. Unique Substrings in Wraparound String 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/unique-s ...

  8. 【LeetCode】516. Longest Palindromic Subsequence 最长回文子序列

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题思路 代码 刷题心得 日期 题目地址:https://le ...

  9. WPF自定义界面WindowChrome

    WPF自定义界面WindowChrome 默认WPF的界面其实也还行,就是满足不了日渐增长的需求,界面还是需要有更高的自定义程度,包括标题栏也要能够塞下更多的操作控件. 默认窗口介绍 新建WPF项目, ...

  10. 写了个适用于vscode的minio图床客户端插件

    缘起 自己搭建minio做我的个人博客图床好一段时间了, 一直用minio自带的web管理后台来上传图片, 它的界面长下面这个样子 上传完后, 需要点下文件列表里刚刚传上去的文件的分享按钮 然后会出来 ...