免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: mingjwan
打印 上一主题 下一主题

对int变量的赋值是原子操作吗? [复制链接]

论坛徽章:
0
51 [报告]
发表于 2006-08-09 23:52 |只看该作者
原帖由 flw2 于 2006-8-9 22:55 发表
如果不是原子操作,就有可能“出现一个线程赋了两个字节,另一个线程来读取数据的情况”。

这个能不能解释一下(单CPU),难道一条指令执行了一半.换别的指令(因为要运行其它线程)?


考虑比较古老的两种386处理器,80386sx和80386ex,这两种处理器与80386的标准版80386dx的主要区别,就在于它们具有不同的数据总线宽度,前两者都是16位的而后者具有32位数据总线。

无论什么处理器,都是要执行
1。取指令
2。指令译码
3。指令执行。
4。返回1。

都是
通过地址总线来交换存储器的地址或i/o端口的编号
通过控制总线来传递控制信号。
通过数据总线来传递存储单元的内容

这一系列过程中,数据总是要通过数据总线来进行交换,当数据总线只有16位宽时,只能分两次传送才能传递32位数据。

论坛徽章:
0
52 [报告]
发表于 2006-08-10 00:02 |只看该作者
那这两个是不是连续的对什么人有影响?
如果是16位数据总线分两次取32位的数据,会被分开吗? 如果会还怎么保证正确性/.

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
53 [报告]
发表于 2006-08-10 00:26 |只看该作者
如果把"赋值"操作限定在指令集上,则所有处理器的指令集操作都是原子的,该原子性由硬件提供。

否则,语言层面的"赋值"操作很难说是否是原子的。

比如说一个例子,a, b都放在存储区里:

  1. int a = 10;
  2. int b = 1;
  3. int
  4. main()
  5. {
  6.     b = a;       //赋值
  7.     return 0;
  8. }
复制代码

那么在X86上的汇编(没有优化)是[gcc 3.3.3]

  1. movl a, %eax
  2. movl %eax, b
复制代码

显然,虽然两条movl是原子的,但是b = a;这样的赋值操作不是。

而同样的赋值语句b = a;在load-store型的arm上,结果是[gcc3.3.6 arm-cross]

  1. ldr r3, .L2                  #取a的地址,放在r3
  2. ldr r2, [r3, #0]          #[]操作取r3地址里的值,放在r2
  3. ldr r3, .L2+4             #取b的地址,放在r3
  4. str r2, [r3, #0]          #赋值
  5. ...
  6. L2:
  7.     .word a
  8.     .word b
复制代码

这就更明显。由于a,b都是存储区变量,赋值b = a;被翻译成4条指令集语句。

[ 本帖最后由 gvim 于 2006-8-10 00:28 编辑 ]

论坛徽章:
0
54 [报告]
发表于 2006-08-10 08:02 |只看该作者
原帖由 gvim 于 2006-8-10 00:26 发表
如果把"赋值"操作限定在指令集上,则所有处理器的指令集操作都是原子的,该原子性由硬件提供。

否则,语言层面的"赋值"操作很难说是否是原子的。

比如说一个例子,a, b都放在存储区里: ...



这个说法赞同滴

论坛徽章:
0
55 [报告]
发表于 2006-08-10 08:39 |只看该作者
原帖由 whyglinux 于 2006-8-9 19:25 发表
...对于这样的系统,对 int 变量的赋值是否是原子操作还取决于此数据在内存中是否已经对齐:如果变量是内存对齐的话,那么就有可能是原子操作;如果非内存对齐,那么一个 int 数据要分至少两次才能完成,就不是原子操作了...

没有对齐的数据虽然要分两个时钟周期才能获取,但是并不影响这条机器指令的原子性。即使这个时候有中断发生,也是在赋值语句完成之后才会进入中断处理程序。

论坛徽章:
0
56 [报告]
发表于 2006-08-10 08:41 |只看该作者
原帖由 flw2 于 2006-8-9 22:55 发表
如果不是原子操作,就有可能“出现一个线程赋了两个字节,另一个线程来读取数据的情况”。

这个能不能解释一下(单CPU),难道一条指令执行了一半.换别的指令(因为要运行其它线程)?

机器指令总是具有原子性的,不可能被中断(除非断电或者硬件设计问题)。

论坛徽章:
0
57 [报告]
发表于 2006-08-10 08:44 |只看该作者
原帖由 isjfk 于 2006-8-10 08:39 发表

没有对齐的数据虽然要分两个时钟周期才能获取,但是并不影响这条机器指令的原子性。即使这个时候有中断发生,也是在赋值语句完成之后才会进入中断处理程序。



能否给个例子,搞段有 “没对齐数据” 的程序来分析一下

论坛徽章:
0
58 [报告]
发表于 2006-08-10 08:52 |只看该作者
原帖由 gvim 于 2006-8-10 00:26 发表
如果把"赋值"操作限定在指令集上,则所有处理器的指令集操作都是原子的,该原子性由硬件提供。

否则,语言层面的"赋值"操作很难说是否是原子的。

比如说一个例子,a, b都放在存储区里: ...

这个说法我认同。


不过我觉得就算赋值语句编译成了两条机器指令,也不影响赋值的原子性。因为就算是两条语句中间被中断打断,然后源数据和目的数据被中断修改,但是返回之后寄存器的值并没有改变,赋值操作继续执行,数据仍然写入了目的地址。这同真正的原子操作结果是一样的。


最糟糕的情况就是赋值之后目的地址里存储的不一定是刚才赋值的数据,对于真正的原子操做这也是一样的。

论坛徽章:
0
59 [报告]
发表于 2006-08-10 08:55 |只看该作者
原帖由 mik 于 2006-8-10 08:44 发表



能否给个例子,搞段有 “没对齐数据” 的程序来分析一下

不用什么程序,看看 Intel CPU datasheet 的时序图就可以理解。而且如果没有逻辑分析仪,用GDB这样的调试器也无法理想的调试“数据没有对齐”的情况。

论坛徽章:
0
60 [报告]
发表于 2006-08-10 18:01 |只看该作者
原帖由 isjfk 于 2006-8-10 08:39 发表

没有对齐的数据虽然要分两个时钟周期才能获取,但是并不影响这条机器指令的原子性。即使这个时候有中断发生,也是在赋值语句完成之后才会进入中断处理程序。


明白了,谢谢指正。看来我一直在这里存在着错误的认识。自己也写了个小程序,发现即使对没有对齐的 int 访问,在写数据的时候是用一条指令来完成的,而不是我以前误认为的对应着两条写指令。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP