12-4 volatile

1. 使用情况        

        volatile 与 12-3 中的代码重排序有关。在 12-3 的第三小节,由于添加 set(CMAKE_C_FLAGS "-O3") 导致编译器对汇编指令进行了优化。此时可使用 volatile 关键字,确保被修饰的变量对应的汇编指令不被优化

#include <stdio.h>
#include <tinycthread.h>

int flag = 0;

int a = 0;
int x = 0;

int T1(void *arg){
  a = 2;
  flag = 1;
  a = a + 3;
  return 0;
}

int T2(void *arg){
  while (flag == 0){}
  x = a * a;
  return 0;
};

void TestVisibilityByThread(){
  thrd_t t_1;
  thrd_t t_2;

  // create two threads to run the Counter function
  thrd_create(&t_2, T2, NULL);
  thrd_create(&t_1, T1, NULL);

  // free up resources
  thrd_join(t_1, NULL);
  thrd_join(t_2, NULL);

  printf("a: %d\n", x);  
}

int main(){

  int count = 0;
  while (count < 10){
    TestVisibilityByThread();
    count++;
  }

  return 0;
}

        12-3 的第三小节代码如上所示。此时查看 a = 2, a = a + 3; 以及 while(flag == 0) 对应的汇编指令(已优化):

         对上述代码做部分修改,将 flag 和 a 的变量类型前添加 volatile 关键字。此时查看优化后的 a = 2, a = a + 3; 以及 while(flag == 0) 对应的汇编指令:

volatile int flag = 0;
volatile int a = 0;

         可以发现,使用 volatile 关键字修饰的变量,其对应的汇编指令并未被优化。对比 12-3,上图中的指令与未优化的编译指令相同。

 2. 注意点

        1)volatile 本身并非为并发程序设计,仅仅与代码重排序有关

        2)volatile 的目的是禁止编译器优化读写操作

        3)volatile 不会保证访问的原子性,操作原子性与否与 volatile 无关

        4)与其他语言(例如 Java)的 volatile 不要混淆,不同语言同一关键字功能不同

        5)特别地,MSVC 赋予 volatile 强制刷新缓存的语义,保证其可见性(12-3 的第二小节)。但由于其他编译器并没有实现此功能,故不能太过依赖

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值