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 ...
随机推荐
- poj2019 二维RMQ模板题
和hdu2888基本上一样的,也是求一个矩阵内的极值 #include<iostream> #include<cstring> #include<cstdio> # ...
- 格式化输出的方法:%、.format()、f
a = '123'a1 = '456'a2 = '789' %占位符 text = "a=%s"%atext1 = "a=%s,a1=%s,a2=%s"%(a, ...
- each()遍历
在<jQuery教程/理解选取更新范围>一节中,我们知道:当选择器返回了多个元素时,可以使用一个方法来更新所有的元素,不再需要使用循环. 然后有的时候需要遍历元素,怎么办? 使用each( ...
- JQuery动画详解(四)
一:基本动画show()显示隐藏的匹配元素.这个就是 'show( speed, [callback] )' 无动画的版本.如果选择的元素是可见的,这个方法将不会改变任何东西.无论这个元素是通过hid ...
- tomcat常用的配置
这里我们使用tomcat版本:apache-tomcat-7.0.77-windows-x64.zip 为例:下载链接地址为:https://archive.apache.org/dist/tomca ...
- dll反编译工具总结
有好多.net程序有加密狗或者有验证,如果exe或dll没有做过特殊处理,破解.net程序其实很简单,不过你要有足够的耐心! 我只做个简单的小例子,把公司的软件破解了,不要被老大知道,吼吼~~~~ 1 ...
- 021 使用join()将数组转变为字符串
1.定义用用法 join() 方法用于把数组中的所有元素放入一个字符串. 元素是通过指定的分隔符进行分隔的. 语法 arrayObject.join(separator) 返回值 返回一个字符串.该字 ...
- 060 关于Hive的调优(本身,sql,mapreduce)
1.关于hive的优化 ->大表拆分小表 ->过滤字段 ->按字段分类存放 ->外部表与分区表 ->外部表:删除时只删除元数据信息,不删除数据文件 多人使用多个外部表操作 ...
- python str,list,tuple转换
1. str转listlist = list(str) 2. list转strstr= ''.join(list) 3. tuple list相互转换tuple=tuple(list)list=l ...
- python使用 requirements.txt 管理所需的包
使用 requirements.txt 管理所需的包 2019/01/28 作者 若要与其他人共享项目.使用生成系统,或打算将项目复制到需要在其中还原环境的其他任何位置,必须指定项目需要的外部包. 建 ...