windows多线程--原子操作
推荐参考博客:秒杀多线程第三篇 原子操作 Interlocked系列函数
原子操作就是不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何线程切换。 本文地址
首先从一个简单的例子来看,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次WaitForSingleObject
int 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
windows多线程--原子操作的更多相关文章
- 总结windows多线程同步互斥
windows多线程同步互斥--总结 我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同 ...
- windows多线程同步互斥--总结
我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同步--临界区 windows多线程同步 ...
- windows多线程编程星球(一)
以前在学校的时候,多线程这一部分是属于那种充满好奇但是又感觉很难掌握的部分.原因嘛我觉得是这玩意儿和编程语言无关,主要和操作系统的有关,所以这部分内容主要出现在讲原理的操作系统书的某一章,看完原理是懂 ...
- Windows多线程多任务设计初步(转)
Windows多线程多任务设计初步 [前言:]当前流行的Windows操作系统,它能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程 ...
- windows多线程没那么难
windows多线程没那么难 作者:vpoet mail:vpoet_sir@163.com 上一博文中我们引入了CreateThread()多线程编程一个简单的例子,事实上我说windows 多线程 ...
- Windows多线程
//简单的引出多线程是肿么回事儿....当点击下载的时候,下载内容还没结束也可以点击资源库,其实这就用了另一个线程,弹出“下载完成”对话框的时候,没有点击确定是不能点击主页面内容的,这就是用----- ...
- Windows多线程学习随笔
自学Windows多线程知识,例程如下: #include <iostream> #include <windows.h> #include <process.h> ...
- windows多线程同步--临界区
推荐参考博客:秒杀多线程第五篇 经典线程同步 关键段CS 关于临界区的观念,一般操作系统书上面都有. 适用范围:它只能同步一个进程中的线程,不能跨进程同步.一般用它来做单个进程内的代码快同步,效率 ...
- windows多线程接口介绍和使用
一windows多线程接口: 1 创建线程 CreateThread 与 _beginthreadex都可以实现创建线程,两个函数的参数 相同, HANDLEWINAPICreateThread( L ...
随机推荐
- python 全栈开发,Day114(装饰器,排序规则,显示列,添加按钮,定制ModelForm,自定义列表页面,自定制URL)
一.装饰器 装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象. 装饰器的应用场景:比如插入日志,性能测试,事务处理, ...
- Web开发.net framework 类库中必须掌握的命名空间(或者类)【转】
Web开发常用命名空间和类. System.Collections //命名空间包含接口和类,这些接口和类定义各种对象(如列表.队列.位数组.哈希表和字典)的集合.System.Collections ...
- 二.hadoop环境搭建
目录: 目录见文章1 文章:官方文档hadoop2.7.4 目的 这篇文档的目的是帮助你快速完成单机上的Hadoop安装与使用以便你对Hadoop分布式文件系统(HDFS)和Map-Reduce框架有 ...
- 关于C#中”扩展方法必须在非泛型静态类中定义“问题的解决
问题描述: 在某个窗口下的编码中使用了以下扩展方法FindControl,以求根据字符串的值去操作控件(本文中的控件为Label控件)的属性. public static Control FindCo ...
- Mysql innodb_fast_shutdown
innodb_fast_shutdown有3个值: 默认是1 可选0 1 2 支持全动态局设置 使用场景:在做数据库关闭升级的时候 set global innodb_fast_shutdown=0 ...
- 在VS Code中对Python进行单元测试
在VS Code中对Python进行单元测试 Python扩展支持使用Python的内置unittest框架以及pytest和Nose进行单元测试.要使用pytest和Nose,必须将它们安装到当前的 ...
- ADI SHARC 学习之PLL
PLL Block Diagram Power Management Registers (PMCTL, PMCTL1)The following sections descr ...
- POJ 2318 TOYS (叉乘判断)
<题目链接> 题目大意: 给出矩形4个点和n个挡板俩顶点的位置,这n个挡板将该矩形分成 n+1块区域,再给你m个点的坐标,然你输出每个区域内有几个点. 解题思路: 用叉乘即可简单判断点与直 ...
- P2376 [USACO09OCT]津贴Allowance
P2376 [USACO09OCT]津贴Allowance一开始想的是多重背包,但是实践不了.实际是贪心,让多c尽可能少,所以先放大的,最后让小的来弥补. #include<iostream&g ...
- 在deepin中安装docker
用往常方法安装 一般在Linux中安装docker的时候都会使用这条命令 wget -qO- https://get.docker.com/ | sh 而在deepin这么做缺不行 打开网址即可发现支 ...