博客
关于我
C/C++编程教训----函数内静态类对象初始化非线程安全(C++11之前)
阅读量:637 次
发布时间:2019-03-14

本文共 1231 字,大约阅读时间需要 4 分钟。

C++静态变量的线程安全问题

背景

在日常开发中,许多程序员会在函数内使用静态变量,这样可以在函数内持久地记录某些信息,同时确保变量只能在函数内使用。不过,函数内静态的类对象初始化却存在一个线程安全问题,这个问题在我们的项目中导致了log4cxx封装接口的调用失败。

问题分析

我们的项目封装了log4cxx的接口,调用了getWarn这个函数。由于getWarn函数内部使用了静态变量来初始化一个Level对象,导致程序在多线程环境下Crash。

为了深入分析这个问题,博主制作了一个简单例子,研究这个静态变量为何在多线程环境下不安全。这个例子用了一个TestObject类,通过TestFunction函数返回一个静态TestObject对象。

例子

class TestObject {public:    int m_iVal;    TestObject() {        m_iVal = 4;    }};TestObject TestFunction() {    static TestObject obj;    return obj;}

这个代码在TestFunction函数中定义了一个静态对象obj,这个对象在TestFunction第一次被调用时会初始化,之后每次调用都会返回同一个obj。

线程安全问题

  • 初始化顺序:obj的构造函数只有在TestFunction第一次被调用时才会被调用,这意味着在多线程环境下,一个线程可能在另一个线程还未完成obj的初始化时,直接读取obj的成员变量,导致初始化的成员变量并没有被设置好。

  • 竞态条件:如果两个线程同时进入TestFunction,第一个线程在完成obj的初始化后,可能移动到了一个与第二个线程竞争的位置,导致第二个线程误认为obj已经被初始化,而实际上obj还未完全构造好。

  • 通过反汇编码可以看出,编译器在静态变量的初始化过程中引入了一种机制,比如通过一个标志位判断对象是否已被初始化。如果对象已经被初始化,直接返回它;否则,才会真正地初始化它,并调用构造函数。如果有多个线程同时进入这个过程,可能会出现竞态条件,使得对象的初始化结果不确定。

    C++11 线程安全支持

    在C++11中,Visual Studio 2015引入了一种新的机制来确保静态对象的线程安全。你可能通过某些内置函数,比如 _Initialize_Thread_header_Init_thread_footer 来实现这一点。这些函数在编译时默认是启用的,可以通过编译选项 /Zc:threadSafeInit= 来禁用。

    总结

  • C++11前:尽量避免在函数内使用静态静态对象。
  • 条件允许时:将编译器升级到支持C++11的版本,比如Visual Studio 2015或更高,以利用内置的线程安全机制。
  • 这种优化不仅解决了静态变量的线程安全问题,还提升了代码的整体质量,使得代码更容易维护和扩展。

    转载地址:http://xygoz.baihongyu.com/

    你可能感兴趣的文章
    nullnullHuge Pages
    查看>>
    numpy 用法
    查看>>
    Numpy如何使用np.umprod重写range函数中i的python
    查看>>
    oauth2-shiro 添加 redis 实现版本
    查看>>
    OAuth2.0_JWT令牌-生成令牌和校验令牌_Spring Security OAuth2.0认证授权---springcloud工作笔记148
    查看>>
    OAuth2.0_JWT令牌介绍_Spring Security OAuth2.0认证授权---springcloud工作笔记147
    查看>>
    OAuth2.0_介绍_Spring Security OAuth2.0认证授权---springcloud工作笔记137
    查看>>
    OAuth2.0_完善环境配置_把资源微服务客户端信息_授权码存入到数据库_Spring Security OAuth2.0认证授权---springcloud工作笔记149
    查看>>
    OAuth2.0_授权服务配置_Spring Security OAuth2.0认证授权---springcloud工作笔记140
    查看>>
    OAuth2.0_授权服务配置_令牌服务和令牌端点配置_Spring Security OAuth2.0认证授权---springcloud工作笔记143
    查看>>
    OAuth2.0_授权服务配置_客户端详情配置_Spring Security OAuth2.0认证授权---springcloud工作笔记142
    查看>>
    OAuth2.0_授权服务配置_密码模式及其他模式_Spring Security OAuth2.0认证授权---springcloud工作笔记145
    查看>>
    OAuth2.0_授权服务配置_资源服务测试_Spring Security OAuth2.0认证授权---springcloud工作笔记146
    查看>>
    OAuth2.0_环境介绍_授权服务和资源服务_Spring Security OAuth2.0认证授权---springcloud工作笔记138
    查看>>
    OAuth2.0_环境搭建_Spring Security OAuth2.0认证授权---springcloud工作笔记139
    查看>>
    oauth2.0协议介绍,核心概念和角色,工作流程,概念和用途
    查看>>
    OAuth2:项目演示-模拟微信授权登录京东
    查看>>
    OA系统多少钱?OA办公系统中的价格选型
    查看>>
    OA系统选型:选择好的工作流引擎
    查看>>
    OA项目之我的会议(会议排座&送审)
    查看>>