首页 > 试题广场 >

i的初始值为0,i++在两个线程里面分别执行100次,能得到

[填空题]
i的初始值为0,i++在两个线程里面分别执行100次,能得到最大值是1,最小值是2
推荐
最大值200,最小值2;
i++只需要执行一条指令,并不能保证多个线程i++,操作同一个i,可以得到正确的结果。因为还有寄存器的因素,多个cpu对应多个寄存器。每次要先把i从内存复制到寄存器,然后++,然后再把i复制到内存中,这需要至少3步。从这个意义上讲,说i++是原子的并不对。

如此,假设两个线程的执行步骤如下:

1. 线程A执行第一次i++,取出内存中的i,值为0,存放到寄存器后执行加1,此时CPU1的寄存器中值为1,内存中为0;

2. 线程B执行第一次i++,取出内存中的i,值为0,存放到寄存器后执行加1,此时CPU2的寄存器中值为1,内存中为0;

3. 线程A继续执行完成第99次i++,并把值放回内存,此时CPU1中寄存器的值为99,内存中为99;

4. 线程B继续执行第一次i++,将其值放回内存,此时CPU1中的寄存器值为1,内存中为1;

5. 线程A执行第100次i++,将内存中的值取回CPU2的寄存器,并执行加1,此时CPU2的寄存器中的值为2,内存中为1;

6. 线程B执行完所有操作,并将其放回内存,此时CPU1的寄存器值为100,内存中为100;

7. 线程A执行100次操作的最后一部分,将CPU2中的寄存器值放回内存,内存中值为2;

8. 结束!

所以该题目便可以得出最终结果,最小值为2,最大值为200。

编辑于 2015-01-31 10:29:46 回复(1)
首先i++不是原子操作,汇编代码是有三句的。
我主要解释一下为什么最小值是2?
① 线程A拿走数据,执行的特别慢,执行了一次就卡主了。
② 线程B拿走数据,执行i++99次后,i此时为99,放回内存。
③ 线程A放回内存时,将原先99覆盖,变成了1.
④ 此时,线程B从内存中拿出数据,执行一次后结束,放回内存,i=2
发表于 2017-07-06 21:05:22 回复(1)
为何线程在两个cpu上执行,都绑定到一个core上不行吗
发表于 2016-11-30 07:29:45 回复(0)
线程1取出i值计算一次,放回去之前,线程2也取出i值计算并放回内存,执行99次,i值为99。此时线程1放回结果,i值为1。
然后线程2取出i值进行最后一次计算,放回去之前,线程1完成了所有次数的运算并将数据放回内存,此时线程2将结果放回内存,i值为2。
发表于 2015-08-07 21:49:29 回复(0)
最小值2的分析:
假设两个线程a,b
首先a执行99次,i为99,在未被写入内存时,b取i=0时执行1次,写入内存后i=1,此时覆盖掉了i=99的值;
然后a取i=1执行1次,b取i=1执行99次,当a比b后写入内存时,a覆盖掉b,此时i=2
编辑于 2015-08-10 22:22:55 回复(1)

最小值是 2 情况分析

线程 1                                                   ( 内存 )                          线程 2

                                                               i = 0

 

1. 读取 i = 0

2. 执行 i++ 99

                                                                                         3. 线程 2 从内存总读入 i
                                                                                         i =0

 

 

4. i = 99  -> i = 99 写回内存            i = 99            

                                                                                          5. 执行 i++ 一次, i = 1

                                                                                           6. i=1 写入到内存中

                                                         i = 1

7. 读入 i=1 ,执行一次 i++

   得到 i = 2

   共计 100 次累加操作结束                                

                                                                                    8. 读入 i = 1 ,
                                                                                    执行 i++ 99 次直至结束得到

                                                                                     i = 100

                                                                                                      

                                                                                  9. i = 100 写回内存中

                                                                                            

                                                         i = 100

 

10 i=2 写入到内存中                      i = 2

编辑于 2015-10-29 23:10:33 回复(1)
线程A 拿了个0,放在手里,等线程B计算到最后一步,写入i,i变成了1。
此时线程B拿到这个1,一直等到线程A计算完,线程B再完成计算,i变成2。
为什么不能更小呢?比如i = 1.
因为必须要两次覆盖才能最小。线程A和线程B一直都在使i变大。i变小的唯一途径就是被另外一个线程覆盖。
所以要想线程A的值变小,线程B必须覆盖一次A,线程B的值要想变小就必须被线程A覆盖一次。
覆盖意味着什么?
覆盖意味着i++,拿到i,i加1,然后写回。
两次覆盖就加两次。所以i最小为2.


发表于 2015-11-14 13:21:11 回复(0)
i++不是原子操作,也就是说,它不是单独一条指令,而是3条指令:
1、从内存中把i的值取出来放到CPU的寄存器中
2、CPU寄存器的值+1
3、把CPU寄存器的值写回内存
如果是单线程操作,i++毫无问题;但是在多核处理器上,用多线程来做i++会有什么问题呢?
我再仔细地重复一遍问题:进程有一个全局变量i,还有有两个线程。每个线程的功能,就是循环100次,执行i++。问线程代码全部执行完毕后,i的值是否一定是200?如果不是,它的最大最小值是多少?
=========分析=======
i++是由3条指令构成的运算操作,两个线程在i变量上共计需要执行100(次循环)*3(条指令)*2(个线程)=600条指令,这600条指令在某种排列下会导致最终i的值仅为2。
(下面是我复制过来的)
假设两个线程的执行步骤如下: 
 1. 线程A执行第一次i++,取出内存中的i,值为0,存放到寄存器后执行加1,此时CPU1的寄存器中值为1,内存中为0;
 2. 线程B执行第一次i++,取出内存中的i,值为0,存放到寄存器后执行加1,此时CPU2的寄存器中值为1,内存中为0;
 3. 线程A继续执行完成第99次i++,并把值放回内存,此时CPU1中寄存器的值为99,内存中为99;
 4. 线程B继续执行第一次i++,将其值放回内存,此时CPU2中的寄存器值为1,内存中为1;
 5. 线程A执行第100次i++,将内存中的值取回CPU1的寄存器,并执行加1,此时CPU1的寄存器中的值为2,内存中为1;
 6. 线程B执行完所有操作,并将其放回内存,此时CPU2的寄存器值为100,内存中为100; 
 7. 线程A执行100次操作的最后一部分,将CPU1中的寄存器值放回内存,内存中值为2;
发表于 2015-11-12 20:23:02 回复(2)
2一开始就执行了,等1线程执行了99次,然后2线程才用1把值覆盖写入.....
然后
2线程又做99次,都写到100了、、、然后线程1最后那次写的特别慢,才写上去,把2写入...
发表于 2016-11-09 19:48:36 回复(0)
2一开始就执行了,等1线程执行了99次,然后2线程才用1把值覆盖写入.....
然后
2线程又做99次,都写到100了、、、然后线程1最后那次写的特别慢,才写上去,把2写入...
发表于 2017-06-27 08:38:08 回复(0)
for(*100次*){
    i++;
}
难道不是每一次迭代都要返回给内存中的i么,怎么会一直给寄存器中的值累加n次?这是C++编译器的优化么?不懂

奥,懂了,懂了,第一名的答案仔细看下去就好了。
编辑于 2017-03-16 22:55:07 回复(0)
求解,为毛最小不是1
发表于 2016-09-16 11:09:02 回复(0)
答案:最小值100  最大值200
题目没有给出i的初始值,我们假设i的初始值为0,否则题目没法做
两个线程分别记为线程1和线程2,i++相当于取出i的值,加1,再放回去
第一种极端情况:每次线程一取出i的值后CPU时间切换到线程二,线程二也取出i的值,取到的值和线程一相等,线程二给i加一后放回去,线程一也将i加一后放回去,放回去的值也相等,相当于两个线程都执行一次i++操作,i的值只增加1,这样操作100次i的值为100
第二种极端情况:线程一和线程二间隔操作,即线程一对i++操作完成,把已经加一的数据放回去之后线程二再操作,轮流进行,最后每个线程都对i加了100次,i的值为200
发表于 2015-01-28 16:10:10 回复(1)
题目有问题,i的初始值是多少?
++运算并非原子操作,cpu需要执行三次指令才可以完成。读变量值-->+1操作-->写回变量的值。多线程执行时线程的执行顺序是不确定的。
最小值情况:线程A执行读变量操作,线程B执行100次i++运算完毕,线程A执行+1操作和写回变量操作,此时i的值为1。
最大值情况:两个线程正好不冲突,都没有读取到过脏数据,此时最大值为200。
发表于 2015-01-22 16:21:58 回复(1)
i的初值是什么?
假设是0
http://zhan.renren.com/h5/entry/3602888498047361672

不理解。  是否可以验证?
发表于 2015-01-12 16:55:53 回复(0)