int a = 1;
void foo() {
a;
}
gcc volatile_test.c -O2 -S && cat volatile_test.s
foo:
.LFB0:
.cfi_startproc
rep
ret
.cfi_endproc
volatile int a = 1;
void foo() {
a;
}
gcc volatile_test.c -O2 -S && cat volatile_test.s
foo:
.LFB0:
.cfi_startproc
movl a(%rip), %eax //从a的内存位置读取值到eax寄存器
ret
.cfi_endproc
//全局定义
int flag=10;
//线程1
void wait() {
int count = 1;
while ( flag != count ) {
count = ~count;
}
}
//线程2
void wake() {
flag = 1;
}
wait:
.LFB0:
.cfi_startproc
movl flag(%rip), %edx //从内存里读取flag
cmpl $1, %edx
je .L1
movl $1, %eax
.p2align 4,,10
.p2align 3
.L3:
notl %eax
cmpl %edx, %eax //直接使用edx, 不再去内存里面获取flag的内存值
jne .L3
wait:
.LFB0:
.cfi_startproc
movl flag(%rip), %eax
cmpl $1, %eax
je .L1
movl $1, %eax
.p2align 4,,10
.p2align 3
.L3:
movl flag(%rip), %edx //再次从内存里面把flag读到寄存器edx
notl %eax
cmpl %eax, %edx
jne .L3
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
volatile int flag=10; //这里是否由volatile, 结果不同
void* wait(void* param) {
int count = 1;
while ( flag != count ) {
count = ~count;
}
printf("wait\n");
}
void* wake(void* param) {
flag = 1;
printf("wake\n");
}
int main () {
pthread_t t[2];
pthread_create(&t[0], NULL, wait, NULL);
sleep(1);
pthread_create(&t[1], NULL, wake, NULL);
while(1);
}int A,B;
void foo() {
A = B+1;
B = 5;
}
movl B(%rip), %eax addl $1, %eax //先做加法 movl %eax, A(%rip) movl $5, B(%rip) //再赋值为5
movl B(%rip), %eax movl $5, B(%rip) //先赋值为5 addl $1, %eax //再执行加法, 顺序调换了 movl %eax, A(%rip)从上面的汇编代码可以看到, 汇编指令的执行顺序, 和原来代码的顺序并不一致.
volatile int A,B;
void foo() {
A = B+1;
B = 5;
}
$gcc cordering.c -S -O2 && cat cordering.s movl B(%rip), %eax addl $1, %eax //先加1 movl %eax, A(%rip) movl $5, B(%rip) //赋值为5
volatile与内存屏障与Acquire&Release语义三者的差别和关系(一),布布扣,bubuko.com
volatile与内存屏障与Acquire&Release语义三者的差别和关系(一)
原文:http://blog.csdn.net/answer3y/article/details/21476787