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