为何对全局变量自增不用一条INC指令搞定,却用了三条指令
为什么对全局变量自增不用一条INC指令搞定,却用了三条指令?
今天看<深入理解计算机系统>的时候看到:两个线程对同一全局变量进行自增操作的时候,由于自增分为三条指令,所以如果两个线程不加同步会产生问题,假如我有一全局变量叫abc,C语言中abc++;这句话被汇编成三句指令:
我就纳闷了,为什么不直接用inc指令直接搞定:
incl abc
是不是不能这样用啊,还是有什么其他原因,这样用的话可以避免线程竞争的问题么?
------最佳解决方案--------------------
有问题, 必须使用 lock 前缀, 以及 memory barrier .. incl 也不比 load-add-store 快..
用 gcc 用 __sync_fetch_and_add 做这件事情, M$WIN 下用 InterlockedXXXX .
------其他解决方案--------------------
x86 下, 一条指令对一个核是原子操作, 不过现在不都是多核么, 并且现在的编译器优化能力很强的, 不加 memory barrier , 根本就没法控制代码里读写内存的顺序, 到时候就是各种诡异的错误.
------其他解决方案--------------------
没优化把,把++放前边试试
------其他解决方案--------------------
应该是编译器没有优化吧
你看看 release 还是不是
------其他解决方案--------------------
incl 是条伪指令吧,反汇编自动展开,不会显示伪指令
------其他解决方案--------------------
是不是用gcc的-O指定优化等级?
------其他解决方案--------------------
incl values这条指令为:
80483b4: ff 05 10 a0 04 08 incl 0x804a010
证明这条指令是可行的,搞不明白为什么不直接这样做
------其他解决方案--------------------
伪指令语句是用于指示汇编程序如何汇编源程序,所以这种语句又叫命令语句。例如源程序中的伪指令语句告诉汇编程序:该源程序如何分段,有哪些逻辑段在程序段中哪些是当前段,它们分别由哪个段寄存器指向;定义了哪些数据,存储单元是如何分配的等等。伪指令语句除定义的具体数据要生成目标代码外,其他均没有对应的目标代码。伪指令语句的这些命令功能是由汇编程序在汇编源程序时,通过执行一段程序来完成的,而不是在运行目标程序时实现的。
网上查到的,很明显inc不是伪指令
------其他解决方案--------------------
用了第二级优化:
gcc -O2 -S test.c
发现自增被优化成一条语句:
addl $1, abc
那两个线程不加同步,同时执行这条语句还有没有问题?
------其他解决方案--------------------
大概明白了,我还一直以为在汇编的角度,一条指令就是一个原子操作。
------其他解决方案--------------------
今天看<深入理解计算机系统>的时候看到:两个线程对同一全局变量进行自增操作的时候,由于自增分为三条指令,所以如果两个线程不加同步会产生问题,假如我有一全局变量叫abc,C语言中abc++;这句话被汇编成三句指令:
movl abc, %eax //load
addl $1, %eax //update
movl %eax, abc //store
我就纳闷了,为什么不直接用inc指令直接搞定:
incl abc
是不是不能这样用啊,还是有什么其他原因,这样用的话可以避免线程竞争的问题么?
------最佳解决方案--------------------
有问题, 必须使用 lock 前缀, 以及 memory barrier .. incl 也不比 load-add-store 快..
用 gcc 用 __sync_fetch_and_add 做这件事情, M$WIN 下用 InterlockedXXXX .
------其他解决方案--------------------
x86 下, 一条指令对一个核是原子操作, 不过现在不都是多核么, 并且现在的编译器优化能力很强的, 不加 memory barrier , 根本就没法控制代码里读写内存的顺序, 到时候就是各种诡异的错误.
------其他解决方案--------------------
没优化把,把++放前边试试
------其他解决方案--------------------
应该是编译器没有优化吧
你看看 release 还是不是
------其他解决方案--------------------
incl 是条伪指令吧,反汇编自动展开,不会显示伪指令
------其他解决方案--------------------
是不是用gcc的-O指定优化等级?
------其他解决方案--------------------
.section .data
values:
.int 30
.section .text
.globl main
main:
incl values
movl $1,%eax
movl $0,%ebx
int $0x80
incl values这条指令为:
80483b4: ff 05 10 a0 04 08 incl 0x804a010
证明这条指令是可行的,搞不明白为什么不直接这样做
------其他解决方案--------------------
伪指令语句是用于指示汇编程序如何汇编源程序,所以这种语句又叫命令语句。例如源程序中的伪指令语句告诉汇编程序:该源程序如何分段,有哪些逻辑段在程序段中哪些是当前段,它们分别由哪个段寄存器指向;定义了哪些数据,存储单元是如何分配的等等。伪指令语句除定义的具体数据要生成目标代码外,其他均没有对应的目标代码。伪指令语句的这些命令功能是由汇编程序在汇编源程序时,通过执行一段程序来完成的,而不是在运行目标程序时实现的。
网上查到的,很明显inc不是伪指令
------其他解决方案--------------------
用了第二级优化:
gcc -O2 -S test.c
发现自增被优化成一条语句:
addl $1, abc
那两个线程不加同步,同时执行这条语句还有没有问题?
------其他解决方案--------------------
大概明白了,我还一直以为在汇编的角度,一条指令就是一个原子操作。
------其他解决方案--------------------