2 aricover aricover 于 2017.12.28 15:49 提问

单核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个回答

caozhy
caozhy   Ds   Rxr 2017.12.29 00:26
已采纳

结果是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 好的,谢谢了
4 个月之前 回复
caozhy
caozhy 回复aricover: 对,你说的这种情况也可能出现。不过单核心实践中非常罕见,因为需要的偶然条件太多。而且windows是20ms切换一次线程,而累加100次的时间是纳秒级别的,所以两个线程各被调度2次的情况在单核上几乎不会发生。
4 个月之前 回复
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的调度方式,单核不能完成这种调度吗
4 个月之前 回复
caozhy
caozhy 然后调度回线程1,mov dword ptr[a],eax,这时候又被覆盖成了1,此时线程2执行完了,不会再覆盖了。线程1还需要执行99次。而不是马上就输出1.所以结果不可能<100
4 个月之前 回复
caozhy
caozhy 回复aricover: 极端的情况下,可能。但是线程1要执行100次,对吧。你这个情况,结果是100.
4 个月之前 回复
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
4 个月之前 回复
aricover
aricover 那请问下,为什么单核cpu不能做到以下这种调度情况:
4 个月之前 回复
leibanxian
leibanxian   2017.12.31 14:39

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

weixin_41303838
weixin_41303838   2017.12.28 18:49

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

qq_36442947
qq_36442947   2017.12.28 16:10

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

aricover
aricover   2017.12.28 16:43

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

aricover
aricover CPU是只有一组,不过切换到自己的时候就把堆栈中保存的之前的值又放到寄存器中。
4 个月之前 回复
weipoiu
weipoiu   2017.12.28 17:59

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

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!