推荐参考博客:秒杀多线程第三篇 原子操作 Interlocked系列函数

原子操作 VS 非原子操作

原子操作就是不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何线程切换。                                          本文地址

首先从一个简单的例子来看,1000个线程同时对一个全局变量(初始化为0)做++操作,最后我们期望的这个变量的值是1000,但是有时候结果却事与愿违:

 #include<string>#include<iostream>#include<process.h>#include<windows.h>using namespace std;volatile int g_cnt;unsigned __stdcall threadFun(void *param)
{g_cnt++;return 0;
}int main()
{for(int j = 0; j < 100; j++){g_cnt = 0;const int threadNum = 1000;HANDLE hth[threadNum];for(int i = 0; i < threadNum; i++)hth[i] = (HANDLE)_beginthreadex(NULL, 0, threadFun, NULL, 0, NULL);//注意WaitForMultipleObjects每次最多等待MAXIMUM_WAIT_OBJECTS个object;//也可以调用1000次WaitForSingleObjectint k = threadNum / MAXIMUM_WAIT_OBJECTS;for(int i = 0; i < k; i++)WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS,&hth[i*MAXIMUM_WAIT_OBJECTS],TRUE, INFINITE);if(threadNum % MAXIMUM_WAIT_OBJECTS != 0)WaitForMultipleObjects(threadNum % MAXIMUM_WAIT_OBJECTS,&hth[k*MAXIMUM_WAIT_OBJECTS],TRUE, INFINITE);for(int i = 0; i < threadNum; i++)CloseHandle(hth[i]);if(g_cnt != 1000)cout<<"the value of g_cnt: "<<g_cnt<<endl;}
}

为什么会这样呢,因为g_cnt++不是一个原子操作,在vs2010中查看反汇编代码为:

对于++操作,编译器把它分为三步:1、从内存中吧g_cnt的值读到寄存器eax,2、eax中的值+1, 3、把eax中的值写会内存

如果有两个线程,线程1执行到第二条语句时,线程2开始执行,那么线程2获取的g_cnt的值还是原来的0(因为线程1还没有执行低三条语句来写回内存),最后g_cnt的值就是1,而不是期望的2;

windows系统提供给了一些函数来保证某些操作的原子性:

LONG __cdecl InterlockedIncrement(LONG volatile* Addend); //变量加1

LONG __cdecl InterlockedDecrement(LONG volatile* Addend);//变量减1

LONG __cdec InterlockedExchangeAdd(LONG volatile* Addend, LONG Value);//变量加上value

LONG __cdecl InterlockedExchange(LONG volatile* Target, LONG Value);//将value的值 赋值 给target指向的变量

以上列出的函数是针对32位的LONG数据的,如果是64位的数据,有其对应的函数,具体可以参考 msdn 列出的所有原子操作函数

针对上面的问题,我们可以把g_cnt++; 改为 InterlockedIncrement((LONG volatile *)&g_cnt);

【版权声明】转载请注明出处:http://www.cnblogs.com/TenosDoIt/p/3602426.html

转载于:https://www.cnblogs.com/TenosDoIt/p/3602426.html

windows多线程--原子操作相关推荐

  1. windows多线程同步互斥--总结

    2019独角兽企业重金招聘Python工程师标准>>> 秒杀多线程面试题系列 参考JustDoIT -- 大部分内容 <Windows核心编程>线程同步对象速查表 对象 ...

  2. Windows多线程编程总结

    Windows 多线程编程总结 keyword:多线程 线程同步 线程池 内核对象 1 内核对象 1 .1 内核对象的概念 内核对象是内核分配的一个内存块,这样的内存块是一个数据结构,表示内核对象的各 ...

  3. windows多线程同步--临界区

    推荐参考博客:秒杀多线程第五篇 经典线程同步 关键段CS 关于临界区的观念,一般操作系统书上面都有. 适用范围:它只能同步一个进程中的线程,不能跨进程同步.一般用它来做单个进程内的代码快同步,效率比较 ...

  4. Windows多线程控制台程序

    学习笔记 Windows多线程控制台程序目的:学习和掌握如何编写Windows多线程控制台程序.通过编写程序,加深对进程和线程关系的理解,掌握多线程程序的执行和编写技巧.设计要求:写一个单进程多线程的 ...

  5. 【转】windows多线程CreateThread与_beginthreadex本质区别

    本文将带领你与多线程作第一次亲密接触,并深入分析CreateThread与_beginthreadex的本质区别,相信阅读本文后你能轻松的使用多线程并能流畅准确的回答CreateThread与_beg ...

  6. windows多线程详解

    转自:http://blog.csdn.net/zhouxuguang236/article/details/7775232 在一个牛人的博客上看到了这篇文章,所以就转过来了,地址是http://bl ...

  7. java 多线程 原子操作_线程安全之原子操作

    原子操作 原子性就是指该操作是不可再分的.不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作. 原子操作可以是一个步骤,也可以是多个步骤,但是其顺序不可以被打乱,也不可以被切割而 ...

  8. Windows多线程多任务设计初步zz

    [前言:]当前流行的Windows操作系统,它能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程 ...

  9. IDM 下载工具利器 - 经典好用优秀的 Windows 多线程加速下载软件

    简介 如果你是一名互联网"老司机",那么一定听过「IDM」这款下载工具的大名!它的全名叫做 Internet Download Manager (互联网下载管理器),缩写就是 ID ...

最新文章

  1. 35岁之后,你还会继续写代码吗?
  2. vue init webpack缺少标识符_vue 如何从单页应用改造成多页应用_vue.js
  3. ios 隔空投安装ipa_ipa文件是什么?怎么安装ipa文件到苹果手机上?
  4. 使用RichTextBox控件实现系统剪切板功能
  5. uvalive 4973 Ardenia
  6. Sublime Text 3 初试牛刀
  7. dev c++ 代码补全_zsh配置与代码自动补全+tmux配置
  8. 根据流程部署ID来获取流程定义图片
  9. [SAP ABAP开发技术总结]ABAP调优——代码优化
  10. 网吧用服务器做虚拟化,刀片、无盘、集群、虚拟化,给你一个选择的理由(上)...
  11. 分子动力学软件-OVITO
  12. PWM波的原理和应用
  13. Python编程之求累乘和
  14. 物联网安全架构与基础设施
  15. google浏览器被2345强制绑定
  16. 运筹学基础(名词解释题总结)
  17. c语言程序设计论文背单词系统,C语言课程设计-背单词系统(含程序)
  18. 『语音信号处理』语音库 librosa 学习
  19. 【日常学习】【二分】【单调队列优化线性DP】codevs3342 绿色通道题解
  20. 参考ggplot2,Seaborn将迎来超大版本更新!

热门文章

  1. java 整数变负数_年年有余之java求余的小技巧
  2. matlab去趋势,[转载]使用Matlab对数据进行去趋势(detrend)
  3. java内存溢出排查top_process-parse-shell
  4. mysql用户权限与安全实例_mysql用户权限管理实例分析
  5. njx如何实现负载均衡_使用Nginx实现负载均衡
  6. transformers Tokenizer
  7. 03 unix 设计哲学和流重定向
  8. MySQL Create Table
  9. 1.11 为什么使用卷积?
  10. opencv-api getAffineTransform()