保证const成员函数的线程安全(C++11/14)—————C++2.0第十一讲_c++ 成员函数 线程安全-程序员宅基地

技术标签: C++基础和特性  c++  atomic  多线程  mutex  数据竞争  

0 结论

  • 保证const成员函数的线程安全,确定它们不会用在并发的语境中;
  • 运用std::atomic类型的变量会比互斥类型好,但std::atomic仅适用于单个变量或内存区域的操作。

1 论据

当存在数据竞险(由多个线程在没有同步的情况下读写同一块内存)时,

  • 如果单个要求的同步的变量或内存区域,使用std::atomic就足够了;
  • 如果有两个或更多变量或内存区域需要作为一整个单位进行操作时,就要用到互斥变量mutex。

1.1 使用std::atomic

以较小的开销运行。

class TestConst{
    
public:
    double testFunc() const noexcept{
    
        ++callCount;
        std::cout<<callCount<<std::endl;
        return x*y;
    }
private:
    mutable std::atomic<unsigned > callCount{
    0};//
    double x{
    2}, y{
    3};
};

#include<thread>

int main(){
    
    TestConst* p = new TestConst();
    std::thread t(&TestConst::testFunc, p);//&X::do_lengthy_work,&my_x
    std::thread t2(&TestConst::testFunc, p);//&X::do_lengthy_work,&my_x
    t.join();
    t2.join();
    delete p;
    }

如果callCount没有mutable的声明,那么在const函数函数中,就会当作const对象处理。

2 使用互斥变量mutex

由于std::mutex是只移动类型(只能移动不能复制),那么它修饰的变量也将失去复制性。

当使用std::atomic时,

class TestConst{
    
public:
    int cal() const{
    
        return 2;
    }

    int testFunc() const{
    
        if (cacheVaild){
    
            return cacheVaild;
        }else{
    
            auto v1 = cal();
            auto v2 = cal();
            cacheVaild = true;
            return cacheValue = v1+v2;
        }
    }

private:
    mutable std::atomic<bool> cacheVaild{
    false};
    mutable std::atomic<int> cacheValue{
    0};
};

可能出现的问题为:当一个线程调用testFunc()并执行到cacheVaild被置为true,这时另一个另一线程也在调用testFunc(),在其观察到cacheVaild值后,就直接返回了一个没有赋值的cacheValue。

解决方法:

class TestConst{
    
public:
    int cal() const{
    
        return 2;
    }

    int testFunc() const{
    
        std::lock_guard<std::mutex> guard(m);//加上互斥量
        if (cacheVaild){
    
            return cacheVaild;
        }else{
    
            auto v1 = cal();
            auto v2 = cal();
            cacheVaild = true;
            return cacheValue = v1+v2;
        }
    }

private:
    mutable  std::mutex m;
    mutable bool cacheVaild{
    false};//不再具备原子性
    mutable int cacheValue{
    0};//不再具备原子性
};

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_33375598/article/details/119334731

智能推荐

Verilog pcie_can_root.xdc_博客 verilog的can通信代码_老皮芽子的博客-程序员宅基地

文章浏览阅读512次,点赞2次,收藏3次。采用 FPGA + SJA1000 实现 PCIe to CANFPGA 约束文件。Xilinx Vivado: pcie_can_root.xdc_博客 verilog的can通信代码

opencv 3.0 填充矩形 填充多边形 fillPoly(图像填充)_opencv3 fillpoly-程序员宅基地

文章浏览阅读5.6k次。参考链接:https://blog.csdn.net/billbliss/article/details/43968291_opencv3 fillpoly

Nature Microbiology | 枯草芽孢杆菌生物膜促进甜瓜生长并抗病_刘永鑫Adam的博客-程序员宅基地

文章浏览阅读1.3k次。文献信息原名:Bacillus subtilis biofilm matrixcomponents target seed oil bodies to promote growth and anti-fungal resistancein melon译名:枯草芽孢杆菌生物膜组分促进甜瓜植株生长,提高植物抗病性期刊:Nature Microbiology发表时间:202..._枯草芽孢杆菌细胞膜成分有哪些

mllib调参 spark_SparkMLlib分类算法之决策树学习-程序员宅基地

文章浏览阅读172次。SparkMLlib分类算法之决策树学习(一) 决策树的基本概念决策树(Decision Tree)是在已知各种情况发生概率的基础上,通过构成决策树来求取净现值的期望值大于等于零的概率,评价项目风险,判断其可行性的决策分析方法,是直观运用概率分析的一种图解法。由于这种决策分支画成图形很像一棵树的枝干,故称决策树。在机器学习中,决策树是一个预测模型,他代表的是对象属性与对象值之间的一种映射关系。En..._mllib fscore调库

一、faster_rcnn_framework.py-程序员宅基地

文章浏览阅读183次。# faster_rcnn_framework.py:该文件实现了 Faster R-CNN 的整体网络结构,并定义了损失函数的计算方式,包括分类损失和边界框回归损失的计算。

随便推点

GTK+2.0之初始学习篇(二)—— g_signal_connect宏解释及HelloWorld-程序员宅基地

文章浏览阅读1w次。GTK+2.0中利用信号/回调函数机制来处理窗口外部传来的事件、消息或信号。 以下实现的是单击窗口关闭按钮,窗口自动关闭。在程序中调用了gtk_main_quit()函数实现退出主循环。#includevoid on_delete_event(); //函数声明int main(int argc, char* argv[]){ GtkWidget *window;_g_signal_connect

太干了!一张图整理了 Python 所有内置异常-程序员宅基地

文章浏览阅读305次。在编写程序时,可能会经常报出一些异常,很大一方面原因是自己的疏忽大意导致程序给出错误信息,另一方面是因为有些异常是程序运行时不可避免的,比如在爬虫时可能有几个网页的结构不一致,这时两种结构的网页用同一套代码就会出错,所以我们就需要捕获出现的异常,以防止程序因为错误信息而终止运行。Python有很多的内置异常,也就是说Python开发者提前考虑到了用户编程过程中可能会出现这类错误,所以制造了这些内置异常可以快速准确向用户反馈出错信息帮助找出代码中的bug。Python官方文档中也给出了所有内置异常及触发条

driver 和 firmware 的区别-程序员宅基地

文章浏览阅读1.5k次。转自http://blog.csdn.net/a15757129260/article/details/53099837驱动和固件(firmware)都是代码,前者为软件服务,后者为硬件服务。在操作系统概念还不明确的时代,二者是没有明显区别的。但是随着计算机体系结构的发展,硬件的种类开始变多,操作系统的种类也变多了。这个时候,因为各种技术的、商业的原因,硬件厂商

Ubuntu Server 16.04 LTS上怎样安装下载安装Nginx并启动-程序员宅基地

文章浏览阅读107次。场景Linux-安装 Ubuntu Server 16.04 X64(图文教程详细版):https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/93790806Nginx入门简介和反向代理、负载均衡、动静分离理解:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/102790862注:博客: https://blog.csdn.net/badao_liumang...

史上最全的Chrome使用技巧集锦_chrome flags设置大全-程序员宅基地

文章浏览阅读1.6w次,点赞2次,收藏16次。史上最全的Chrome使用技巧集锦转自http://www.codeceo.com/article/chrome-usage-most-useful.htmlChrome的隐身模式先来说说隐身模式的启用方法吧1.键盘快捷:Ctrl + Shift + N。2.在Windows7下的任务栏处,右击“Chrome”图标,会出一个下拉菜单,_chrome flags设置大全

闭口式霍尔电流传感器(安科瑞-卓宋兰)_闭口霍尔-程序员宅基地

文章浏览阅读359次。1.产品概述AHKC-BS 系列电流传感器的初、次级之间是绝缘的,可用于测量直流、交流和脉冲电流。2.技术参数及外形尺寸3.安装方式4.注意事项1、霍尔传感器在使用时,为了得到较好的动态特性和灵敏度,要注意原边线圈和副边线圈之间的耦合,建议使用单根导线且导线完全填满霍尔传感器模块过线孔;2、霍尔传感器在使用时,在额定输入电流值下才能得到更佳的测量精度,当被测电流远低于额定值时,若要获得更佳精度,原边可使用多匝,即:IpNp=额定安匝数。另外,原边馈线温度不应超过 80℃;3、霍尔电流传感器_闭口霍尔