• cpu的指令重排,禁用办法


    上一篇博客 volatile关键字总结-CSDN博客,我们讲了两个volatile变量可以限制编译器对指令的重排,但是限制不了cpu层面的指令重排

    这篇博客开始,我们演示下cpu层面的指令重排,以及如何禁止cpu层面的指令重排

    实验一:复现cpu指令重排

    代码如下

    1. #include
    2. #include
    3. using namespace std;
    4. volatile int x = 0;
    5. volatile int y = 0;
    6. volatile int a = 0;
    7. volatile int b = 0;
    8. void threadFun1()
    9. {
    10. // 空循环5万次,这样尽量和线程2同时启动,更容易出现x=0,y=0的结果
    11. for (int i = 0; i < 50000; i++){}
    12. a = 1;
    13. x = b;
    14. }
    15. void threadFun2()
    16. {
    17. b = 1;
    18. y = a;
    19. }
    20. int main()
    21. {
    22. int i = 0;
    23. while (1)
    24. {
    25. i++;
    26. x = y = a = b = 0;
    27. thread t1(threadFun1);
    28. thread t2(threadFun2);
    29. t1.join();
    30. t2.join();
    31. if (x==0 && y == 0)
    32. {
    33. cout << "第" << i << "次执行后,发现x=0,且y=0" << endl;
    34. break;
    35. }
    36. else
    37. {
    38. cout << "第" << i << "次执行后,x=" << x << ",y=" << y << endl;
    39. }
    40. }
    41. return 0;
    42. }

    对上面的代码解释下:

    1. 四个变量x, y, a, b都用volatile关键字修饰,访问时必须从内存读写,确保编译器层面不做任何的指令优化

    2. 线程1函数中,先执行a=1,再执行x=b

    3. 线程2函数中,先执行b=1,再执行y=a

    4. 我们每次先把x,y,a,b置零,然后开启这两个线程

    实验如下图

    第一次执行5万多次出现了,x=0,且y=0的情况

    第二次执行11万多次才出现

    按照逻辑,无论线程1先执行,还是线程2先执行,最终两个线程执行完后都不可能出现x=0且y=0的情况

    因为出现x=0且y=0,这意味着

    要么是 "x=b"先于 "a=1"执行了

    要么是 "y=a"先于 "b=1"执行了

    也就是虽然四个变量都使用volatile关键字,编译器层面没有出现重排,但是cpu层面出现了指令的重排!

    实验二:使用函数__sync_synchronize(),禁止cpu指令重排

    代码如下(仅贴出与实验一不同的地方)

    void threadFun1()
    {
        // 空循环8万次,这样尽量和线程2同时启动,更容易出现x=0,y=0的结果
        for (int i = 0; i < 80000; i++){}

        a = 1;
        __sync_synchronize();
        x = b;
    }

    void threadFun2()
    {
        b = 1;
        __sync_synchronize();
        y = a;
    }

    以上代码:仅仅是在两个语句之间调用了函数 __sync_synchronize();

    注意:这个GCC函数也是linux下用来做内存屏障(memory barrier)的实现原理,防止cpu乱序执行命令

    实验结果:

    执行了1700多万次测试,都不会出现x=0,且y=0的情况了

  • 相关阅读:
    python使用matplotlib.pyplot画图时总会提示“内核似乎挂掉了,很快就会自动重启”
    (十四)OpenCV中的自带颜色表操作cv::LUT
    网易数帆 Envoy Gateway 实践之旅:坚守 6 年,峥嵘渐显
    SVG了解与绘图应用
    java计算机毕业设计高校就业服务网站源码+mysql数据库+系统+lw文档+部署
    Dockerfile
    C++ day7
    leetcode做题笔记162. 寻找峰值
    PT_数字特征_矩协方差相关系数
    惨败阿里,洒泪复习3个月!上岸美团惨遭面试官狂问MySQL
  • 原文地址:https://blog.csdn.net/yzf279533105/article/details/133660494