文档章节

std::call_once

苗永超
 苗永超
发布于 2016/04/07 16:01
字数 542
阅读 84
收藏 1

 在多线程的环境下,有些时候我们不需要某给函数被调用多次或者某些变量被初始化多次,它们仅仅只需要被调用一次或者初始化一次即可。很多时候我们为了初始化某些数据会写出如下代码,这些代码在单线程中是没有任何问题的,但是在多线程中就会出现不可预知的问题。

bool initialized = false; // global flag
if (!initialized) {
    // initialize if not initialized yet
    initialize ();
    initialized = true;
}
or
static std::vector<std::string> staticData;
void foo ()
{
    if (staticData.empty ()) {
        staticData = initializeStaticData ();
    }
    ...
}

    为了解决上述多线程中出现的资源竞争导致的数据不一致问题,我们大多数的处理方法就是使用互斥锁来处理。在C++11中提供了最新的处理方法:使用std::call_once函数来处理,其定义如下头文件#include<mutex>

template< class Function, class... Args >
void call_once ( std::once_flag& flag, Function&& f, Args&& args... );
参数解析Parameters:
flag     -	 an object, for which exactly one function gets executed
f	 -	 需要被调用的函数
args...  -	 传递给函数f的参数(可以多个)
返回值为 (none)
抛出异常
std::system_error if any condition prevents calls to call_once from executing as specified any exception thrown by f

例:

static std::vector<std::string> staticData;
std::vector<std::string>initializeStaticData ()
{
    std::vector<std::string> vec;
    vec.push_back ("initialize");

    return vec;
}

void foo()
{
    static std::once_flag oc;
    std::call_once(oc, [] { staticData = initializeStaticData ();});
}

正如上面的例子所示call_once函数第一个参数是std::once_flag的一个对象,第二个参数可以是函数、成员函数、函数对象、lambda函数。在实际的使用过程中,我们会经常将该函数用于延后初始化或者类的单例实现(Singleton)。

class X {
private:
    mutable std::once_flag initDataFlag;
    void initData ()
    {
        _data = "init";
    }

    std::string _data;
public:
    std::string& getData () {
        std::call_once (initDataFlag, &X::initData, this);
        return _data;
    }
};

关于异常Exception: 由被调用的函数产生出的异常都将会重新抛出,因此你最好有异常处理。如果第一次调用没有成功的话,那么第二次还会继续调用,一次类推直到调用成功为止。

关于程序编译:需要加 -std=c++0x或者-std=c++11和-lpthread选项。

本文转载自:http://blog.csdn.net/cywosp/article/details/8968655

共有 人打赏支持
苗永超
粉丝 15
博文 57
码字总数 14075
作品 0
海淀
后端工程师
私信 提问
C++ std::function 和 std::bind

C++11提供了std::function和std::bind两个工具,用于引用可调用对象。这些可调用对象包括 普通函数,Lambda表达式,类的静态成员函数,非静态成员函数以及仿函数等。引用可调用对象,可以用于...

yepanl
2018/09/23
0
0
c++11实现异步定时器

c++11提供了丰富的时间和线程操作函数,比如 std::this_thread::sleep, std::chrono::seconds等。可以利用这些来很方便的实现一个定时器。 实现 ifndef TIMERH define TIMERH include includ...

moki_oschina
2018/05/23
0
0
I/O: std::ios_base

std::iosbase做为所有stream最底层的类,主要提供 “与字符类型以及其相应之chartraits无关”的: (1), state information (2), control information (3), private storage (4), callbacks 构...

SHIHUAMarryMe
2016/09/11
16
0
Multi thread: std::promise

前面我们了解到可以使用std::sharedfuture/std::sharedfuture在多个其他线程中处理另外一个线程的函数的返回结果. 那么疑问来了,我们要怎样在多线程之间传递数据呢? demo1 :std::promise在线...

SHIHUAMarryMe
2016/05/14
80
0
C++:智能指针-TR1的shared_ptr和weak_ptr使用介绍

shared_ptr: Based on a reference counter model, with the counter incremented each time a new shared pointer object points to the resource, and decremented when the object's dest......

长平狐
2013/01/11
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

cxf框架的介绍

小小小施爷
7分钟前
0
0
35K成功入职:蚂蚁金服面试Java后端经历!

上个月4号通过阿里工作的学长进行内推,7天简历评估,11号接到电话面试,尽管猝不及防回答仓促,但好在前期准备充分,通过。3天后进行现场面试,通知时间为早上10点。当日设了七点闹钟,结果...

别打我会飞
8分钟前
0
0
【HAVENT原创】让 IE6 ~ IE8 浏览器也支持 map 和 filter 方法

Array.prototype 扩展可以让 IE6 ~ IE8 浏览器也支持 map 的方法: if (typeof Array.prototype.map != "function") { Array.prototype.map = function (fn, context) { var arr = [......

HAVENT
8分钟前
0
0
SMSSDK的Unity3D的两种集成方式

SMSSDK的Unity3D插件主要为用户提供了两种集成的方式,一种是通过桥接文件直接调用SMSSDK的原生API,另外一种是集成SMSSDK_Demo中的UI,这两种方式的集成,方便用户根据自己的需要进行不同的...

佳妮
17分钟前
0
0
云计算、大数据、编程语言学习指南下载,100+技术课程免费学!这份诚意满满的新年技术大礼包,你Get了吗?

开发者认证、云学院、技术社群,更多精彩,尽在开发者会场 近年来,新技术发展迅速。互联网行业持续高速增长,平均薪资水平持续提升,互联网技术学习已俨然成为学生、在职人员都感兴趣的“业...

zhaowei121
20分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部