博客
关于我
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/

    你可能感兴趣的文章
    Oracle游标
    查看>>
    oracle游标数最大数,Oracle 最大连接数 最大游标数
    查看>>
    oracle用户改名
    查看>>
    oracle用户解压不了,PLSQL developer 连接不上64位Oracle 的解决方法
    查看>>
    oracle用户解锁
    查看>>
    Oracle用游标删除重复数据
    查看>>
    Tomcat学习总结(19)—— 为什么首选Tomcat作为JavaWeb应用服务器?
    查看>>
    oracle的内置函数
    查看>>
    Oracle的存储结构
    查看>>
    Oracle的聚合函数group by结合CUBE和ROLLUP的使用
    查看>>
    Oracle监听配置、数据库实例配置等
    查看>>
    Oracle知识补充
    查看>>
    Oracle笔记(十三) 视图、同义词、索引
    查看>>
    Oracle笔记(十) 约束
    查看>>
    【BOOST C++字串专题07】 Boost.Format
    查看>>
    oracle系列(六)OEM与常见故障处理
    查看>>
    Oracle系列:安装Oracle RAC数据库(二)
    查看>>
    oracle系统 介绍,ORACLE数据库管理系统介绍
    查看>>
    Thymeleaf模板引擎的编写
    查看>>
    oracle获取数据库表、字段、注释、约束等
    查看>>