本文主要是介绍volatile 与内存屏障,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
编译器和CPU执行过程中,可能会生成或者执行的机器码,可能和我们编写的代码的预期的逻辑不一样,可能会造成一些问题。
单线程中,这样没有问题,因为编译器和CPU可以保证即使有调整,但是最后的结果是预期的。
但在多线程的场景下,可能会有问题,本文只关注多线程修改和访问同一个公共变量的场景。
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>static volatile int vvv = 1;void * thread1(void *n){sleep(2);printf("sss\n");vvv = -1;return NULL;
}
int main() {pthread_t t;int re = pthread_create(&t, NULL, &thread1, NULL);if(re < 0){perror("thread");}while(vvv > 0){__sync_synchronize ();}return 0;
}
如果没有上面第6行或者第21行的代码,并且编译的时候用了-O3的优化选项,编译器会将19 - 21的代码优化成:
while(1){}
所以可能导致死循环。
volatile作用在编译的时候,让编译器生成机器码的时候,一方面,不做优化,老老实实按照代码去翻译,一方面,在运行的时候,被volatile修饰地变量不会被缓存到CPU的寄存器中,每次读都是从内存中去读。这样可以解决上面代码中的问题。
另外一种解决方式就是用形如__sync_synchronize(gcc和X86环境下) 这样的函数,加一个逻辑上无实际意义的代码,依照mem barrier的定义,此语句上面的语句会严格在下面语句之前执行,而且也让编译器的优化在此语句附近失效了,具体的细节需要查看汇编代码来查看(TODO)。
这篇关于volatile 与内存屏障的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!