单核cpu下,有一个变量int a=0;两个线程同时进行a++操作100次,不加锁,最后a的值是?

各位大佬,请教一下这个问题,多核cpu下的线程切换极端情况可以实现最小值为2,这个我大概理解了,但是多核这种调度情况为什么单核不能做到,单核在调度的时候存不存在什么限制。这个问题在网上很常见,但是都没有怎么解释为什么单核为什么最小值是100.
按照汇编指令:
mov eax,dword ptr[a]
add eax,1
mov dword ptr[a],eax
麻烦帮忙解释下最小值为100时,是怎么样调度的

6个回答

结果是100到200之间的某个不确定的数字。这是因为++操作并非原子性造成的。
线程1执行
mov eax,dword ptr[a]
add eax,1
以后,线程如果被中断,切换到另一个线程,并且执行了
mov eax,dword ptr[a]
add eax,1
mov dword ptr[a],eax
注意,此时ptr[a]相比线程1的eax,因为已经被+1了,所以相等
然后线程1执行以下:
mov dword ptr[a],eax
结果是实际上线程1并没有对a实现+1

这种情况会使得结果偏小。

aricover
aricover 好的,谢谢了
一年多之前 回复
caozhy
贵阳老马马善福专业维修游泳池堵漏防水工程 回复aricover: 对,你说的这种情况也可能出现。不过单核心实践中非常罕见,因为需要的偶然条件太多。而且windows是20ms切换一次线程,而累加100次的时间是纳秒级别的,所以两个线程各被调度2次的情况在单核上几乎不会发生。
一年多之前 回复
aricover
aricover 线程1: mov eax,dword ptr[a]--> add eax,1 切换到线程2:mov dword ptr[a]--> add eax,1 -->mov dword ptr[a],eax....总共99次 切换成线程1: mov dword ptr[a],eax (这时候内存是1,相当于线程2的99自加白做了) 切换到线程2: mov eax,dword ptr[a] 然后线程1:mov dword ptr[a]--> add eax,1 -->mov dword ptr[a],eax....总共99次 切换到线程2: add eax,1-->mov dword ptrp[a],eax 这样的话最后的值就是2 (这就是多核cpu下最小值为2的调度方式,单核不能完成这种调度吗
一年多之前 回复
caozhy
贵阳老马马善福专业维修游泳池堵漏防水工程 然后调度回线程1,mov dword ptr[a],eax,这时候又被覆盖成了1,此时线程2执行完了,不会再覆盖了。线程1还需要执行99次。而不是马上就输出1.所以结果不可能<100
一年多之前 回复
caozhy
贵阳老马马善福专业维修游泳池堵漏防水工程 回复aricover: 极端的情况下,可能。但是线程1要执行100次,对吧。你这个情况,结果是100.
一年多之前 回复
aricover
aricover 线程1:mov eax,dword ptr[a] add eax,1 然后线程切换,线程2:mov eax,dword ptr[a] add eax,1 mov dword ptr[a],eax。。。。循环99次,然后调度回线程1,mov dword ptr[a],eax,这时候又被覆盖成了1
一年多之前 回复
aricover
aricover 那请问下,为什么单核cpu不能做到以下这种调度情况:
一年多之前 回复

第一个线程先执行,但是不一定等到100次a++执行完之后,第二个线程才开始执行,第二个线程的执行时间是任意的,多线程条件下线程执行时抢占式的

这里说的一组不是物理上的,而是逻辑上的,说每个线程都需要有一块地址用来做线程让出CPU所有权时保存cpu各个寄存器的值,好在线程重新拥有cpu的时候恢复运行状态。------http://bbs.csdn.net/topics/320063988 yoogera
按照这个逻辑的话,上文的调度情况就不会发生了,重新思考

aricover
aricover CPU是只有一组,不过切换到自己的时候就把堆栈中保存的之前的值又放到寄存器中。
一年多之前 回复

这个还真不好说 建议去看下线程对CPU资源获取的问题

你可以实际看下CPU,最终资源,这个不能太确定

操作系统会给每个线程分配20ms时间运行之后进行切换,当切换回源线程时,原来在栈中存储的值将会重新赋给变量,因此当有线程间的切换时,这个变量实际上少加了几次,所以最终的值会比200小

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
单核cpu下,有一个变量int a=0;两个线程同时进行a++操作100次,不加锁,最后a的值是?
各位大佬,请教一下这个问题,多核cpu下的线程切换极端情况可以实现最小值为2,这个我大概理解了,但是多核这种调度情况为什么单核不能做到,单核在调度的时候存不存在什么限制。这个问题在网上很常见,但是都没有怎么解释为什么单核为什么最小值是100.rn按照汇编指令:rnmov eax,dword ptr[a]rnadd eax,1rnmov dword ptr[a],eaxrn麻烦帮忙解释下最小值为100时,是怎么样调度的rn
int a[100];有关于sizeof(&a)值的一个问题
int a[100];rnrnprintf(“%d,%d,%d,%d\n”,sizeof(a),sizeof(&a),sizeof(a[0]),sizeof(&a[0]);rnrn在VC6.0下运行,上面的结果是400,400,4,4。sizeof(a),sizeof(a[0]),sizeof(&a[0])我都明白是怎么一回事,这里只是拿出来做一个对比,让我不明白的就是为什么sizeof(&a)也是400,&a是整个数组的地址,它难道不应该是一个整型值,大小为4吗?rn
int *a;和int* a
请问int *a;和int* a有什么区别吗
int a=5; a+=a-=a*a; 最后a的值为什么是-15
[img=https://img-bbs.csdn.net/upload/201706/24/1498304316_444125.png][/img]rnrn为什么输出结果是rn[code=java]rn-15rn[/code]rnrn这里按我的理解对第2行进行拆分和推导rn[code=java]rna += a -= 25;rna += (a -= 25);rna += (a = a - 25);rna += (a = 5 - 25);rna += (a = -20);rn//a的值变成-20rna += -20;rna = a -20rna = -20 - 20;rna = -40rn[/code]rn我的结论是-40 请问哪里有问题呢?rn下面是Java的拆分及输出,结果是-40rn[img=https://img-bbs.csdn.net/upload/201706/24/1498304543_421226.png][/img]rnrnrn为什么相同的逻辑代码,C和Java的结果不同呢??我想知道差异性在哪里rnrnrn[img=https://img-bbs.csdn.net/upload/201706/24/1498304333_731768.png][/img]rnrn下面是
int a[10]中a=&a=&a[0]吗?
int a[10]中a=&a=&a[0]吗?不等的话,&a是什么?
int a=0; a=a+++ ++a; 请心算说出a=?
如题,请大家不要试验,心算一下写出答案
if(a==0)和if(0==a)
if(a==0)和if(0==a),为什么推荐后一种写法
两个线程同时对int a=0进行a++一百次最后的结果可能为多少?
关于这个问题csdn的博客上有很多博客都是说为200 首先贴上代码 public class Test { private static int i = 0; public static void main(String[] args) { Runnable runnable = () -&amp;gt; { for (int j = 0; ...
(int*)a[0]和&a[0]有啥区别
a是一个数组名 那么(int*)a[0]和&a[0]有啥区别?
int[] a 和 int* a有什么区别
希望各位高手指点
int a = a ^ a; 没有问题?
我用VS2012确实清零了,定义在主函数里了。
int *a和int* a有什么区别?
int *a和int* a,rn有的说只是风格上的不同,而有的说是对指针的认识rn错误的问题,大家的看法是什么?
int a[0]; 晕~~~~~~~~~~~~~~~~~
int a[0]; 编译器不发生编译错误 rn请问以下代码在调用构造函数创建对象的时候如果rn是这样调用:“stack st”必然生成一个 int item[0] 的错误数组rn但是不编译错误, 请问怎么阻止创建st对象rnrntemplate rnclass stack rn private:rn T item[n]; rn rn rnrn public:rn stack() rn 。。。。。。。。。。。。。。。。。。。。。。rnrn
int a[0]; ???
今天看帖子 看到类似这样一个声明rnint a[0];rn定义了一个成员为0个的数组rn我用vc6的编译器编译 不能通过rn错误提示为(此一行同时引发两个错误)rnerror C2466: cannot allocate an array of constant size 0rnerror C2133: 'a' : unknown sizern发贴的人说代码是linux下写的 用gcc编译rn我没见过这样声明的数组 0个成员? 有没有这样声明的数组呢?这样声明的数组是做什么用的?rn我现在没法试 因为vc6根本就编译不过去。。
jsp<%! int a;%>,<% int a%>中定义变量有什么区别?
jsp<%! int a;%>,<% int a%>中定义变量有什么区别?
int a = ~0;
请问这个~符号是做什么的
int a='0' cout<
多谢!
int a=5; a*=a/a=a++;
int a=5; a*=a/a=a++; 哪位高手 能帮我分解 这个表达式 谢谢了
数组指针 int (*a)[5] 的a,&a和*a ?
int b[5] = 0,1,2,3,4;rnint (*a)[5] = &b;rnrn为什么a,&a和*a的值都是数组b的地址呢?
int a[5]=0 与 int a[5]=0,的区别
int a[5]=0 是将数组a 5个元素初始化为0rnint a[5]=0, 呢?rnrn关键是不是与编译器相关,还是是C语言的标准?
int a=1 (++a)+(++a)+(++a)=?
int a=1rn (++a)+(++a)+(++a)=?rnrn个人感觉这个答案应该是9,但是vc2005运行的结果却是12。rn我是这么分析的:rn首先执行括号里的内容,第一个括号内的++a返回2,同时a自增1,得到a的值为2;rn第二个括号内的++a返回3,同时a自增1,得到a的值为3;rn第三个括号内的++a返回4,同时a自增1,得到a的值为4;rn这是得到了三个括号内返回值的加法算式:2+3+4,得到9。rnrn有谁知道我的分析哪里有问题,请指教。谢谢。
关于int* a和int *a
rn#includernrnvoid test(int *x,int *y);rnrnvoid main()rn rn int a=1,b=2;rn test(&a,&b);rn cout<<"a="<
(int*)a 和int *a什么区别
(int*)a 和int *a什么区别
int a = 4, 当a += a++; a += ++a; ++a +=a 等时,求a的值
求 (1) a += a++;rn (2) a += ++a;rn (3) ++a += a;rn (4) ++a += a++;rn (5) ++a += ++a;rnrn书上说结果是:(1) 9; (2) 10; (3) 10; (4) 11; (5) 12rn不知道怎么算的啊,总感觉糊糊涂涂的,望大神给讲解下
int a = 3; a + = a -= a * a ,最后a为多少
如果知道结果能不能详细解答步骤.
(int)a:与(int&)a
(int)a:与(int&)a的不同,到底如何的?
a[][]----a[0]与&a[0]的区别
a[][]----a[0]与&a[0]的区别...
int a;(&a)++可以吗
本可称为C语言基础课程,讲解C语言基础入门知识。rn本课程是介绍C语言的基础知识,针对所有对计算机体系结构和嵌入式知识感兴趣的学员。
int&* a;和int*& a;
能说说复引用和取地址符用在一起的东东吗?rn举个例子。rn谢谢!
int a=0; int a=new int();本质区别是什么
想知道,这两种声明方式本质上的区别是什么?rn[code=csharp]rnint a=0; rnint a=new int();rn[/code]rn我理解int a=0是栈变量编译器静态分配内存,而int a=new int()使用new操作符CLR运行时在堆上动态分配,但int类型应该是值类型,我看到一些资料写着值类型都应该是栈变量,这个有怎么理解?
int a = (int)(((int*)0)+4); a 等于多少?
int a = (int)(((int*)0)+4); rnrn测试结果16 谁能解释一下?
(int)a、&a、(int)&a、(int&)a的区别
double a=1.0f; cout&amp;lt;&amp;lt;(int&amp;amp;)a&amp;lt;&amp;lt;endl;   输出为0    在Turbo c 3.0中的结果都为0;在VC 6.0中为1065353216和0 (int)a是把float型强类型化为int类型,所以为0; (int&amp;amp;)a是把a地址的前两字节当成一个int类型数据输出;至于为什么Turbo c 3.0中的结果为0,...
C语言基础知识:a a[0] &a &a[0]
一、解析为什么p = a;或者p = &amp;a[0]时类型匹配,p = &amp;a;类型不匹配? int *p; int a[10]; P = a; //a做右值表示数组首元素的首地址,【a做右值等同于&amp;a[0];】;类型匹配,左右两边都是int *型 p = &amp;a; //类型不匹配。原因:p是int * (int类型的指针),而&amp;a是int (*)[10...
int &a,int *&a, int &*a,,,这都是什么东西?
都没在C里头见过这些东西,rnint &a 这是什么类型的变量? 怎么赋值?怎么使用?rnint *&a 这是什么类型的变量? 怎么赋值?怎么使用?rnint &*a 这是什么类型的变量? 怎么赋值?怎么使用?rnrnvoid f(int *&a)rnrnrnint *&a 传进函数里的参数,能在函数里改变原来的值吗?
*((int*)&a)=5 a是对象
分析程序员和黑客的区别rnrn题目:rn  设有如下C++类rnrn class Arnrn int value;rnpublic:rn A(int n = 0) : value(n) rn int GetValue()rn rn return value;rn rn;rnrn  请使用某种方式来在类的外部改变私有成员A::value的值。rnrn rnrn程序员的可能做法:rnrn class Arnrn int value;rnpublic:rn A(int n = 0) : value(n) rn int GetValue()rn rn return value;rn rn void SetValue(int n)rn rn value = n;rn rn;rnrn void f()rnrn rn A a;rn a.SetValue(5);rn rnrn rnrn黑客的可能做法:rnrn void f()rnrn A a;rn *((int *)&a) = 5;rnrn请问*((int*)&a)是强制类型转换吗 我在dev上试了一下 执行过黑客的void f()后a依然是对象 这里是怎么个机制 请教了
int a[]=0,2,3,4,5;问a - &a[4]的值?
int a[]=0,2,3,4,5;问a - &a[4]的值?rnrn因为一个int是占四个字节,所以上面两个指针相减后的值应该是-16;rn但我用int value = a-&a[4]后,value的值却是-4;我看了反汇编代码如下(VS2005):rn 29: int a[] = 0,2,3,4,5;rn004123BE mov dword ptr [a],0 rn004123C5 mov dword ptr [ebp-14h],2 rn004123CC mov dword ptr [ebp-10h],3 rn004123D3 mov dword ptr [ebp-0Ch],4 rn004123DA mov dword ptr [ebp-8],5 rn 30: rn 31: int value = a - &a[4];rn004123E1 lea eax,[ebp-8] rn004123E4 lea ecx,[a] rn004123E7 sub ecx,eax //这个时候相减,ecx里保存的值应该是-16rn004123E9 sar ecx,2 //但这句话把ecx的值右移两位,除了4,why?rn004123EC mov dword ptr [value],ecx rnrn从上面的汇编代码可以看到,在两个指针值相减后,把相减的值除了4,为什么这么做呢?请知情人士指点一下,谢谢.
两个线程运行++a
题目:个线程并发执行以下代码,假设a是全局变量,初始值是1,那么以下输出中()是可能的。void foo ( ) { ++a printf("%d",a); } A. 3_2_ B. 2_3_ C. 3_3_ D. 2_2_ 答案:ABCD解析:++不能认为是原子操作,a是全局变量,在内存中,则++a一般被分为从内存取a到寄存器、+、回写到内存三步,考虑到并发。 设
比如int a[2][3],为什么不能用*a来输出a[0][0]?
[img=https://img-bbs.csdn.net/upload/201311/22/1385101235_925705.jpg][/img]rn如图片中的问题rn附:#includernvoid main()rnrnint a[2][3]=1,2,3,4,5,6;rnprintf("%d\n",&a[0]); //268712rnprintf("%d\n",&a[0][0]); //268712rnprintf("%d\n",a); //2686712 一个地址 (都采用%d表示,方便观察。)rnprintf("%d\n",*a); //2686712 一个地址?rn //a不是代表第一行的首地址么?所以也可以说是第一行第一个元素的地址吧,rn //上面的输出同样验证的确是这样,那为什么*a无法输出具体元素值呢?还是一个地址值?rnprintf("%d\n",*a[0]); //输出1 ,这样肯定是可以输出的(由上面知道&a[0][0]和a等价,rn //那么为什么a[0][0]可以输出数据值,而*a不可以?当然**a肯定可以。)rnchar m[2][3]="ab","cd";rnprintf("%s\n",m);//abrnprintf("%s\n",*m);//abrnrn
int &a和int& a有什么区别
看书上有时候把&放在变量前面,有时候放在类型后面rn有什么区别rn有时候函数声明int f(int&)rn要是这么写的话有啥区别int f(int &)
一维数组的存储类型 , a &a int(a) 的区别
一维数组: int a[3]; 名称 数据类型 值(举例) 意义 a int *   0x0300 数组的 首元素的首地址 &a[0] int * 0x0300 数组的 首元素的首地址 &a int (*)[3]
相关热词 c#部署端口监听项目、 c#接口中的属性使用方法 c# 昨天 c#func链接匿名方法 c#怎么创建文件夹 c#从键盘接收空格 c#da/ad c#部门请假管理系统 c#服务器socket c# 默认的访问修饰符