栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++多线程03 Lambda表达式与caII once

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++多线程03 Lambda表达式与caII once

一、Lambda表达式做为线程入口

Lambda(匿名函数)表达式是C++11最重要的特性之一,lambda来源于函数式编程的概念,也是现代编程语言的一个特点。

优点如下:

声明式编程风格:就地匿名定义目标函数或函数对象,有更好的可读性和可维护性。
简洁:不需要额外写一个命名函数或函数对象,,避免了代码膨胀和功能分散。
更加灵活:在需要的时间和地点实现功能闭包。
概念及基本用法
lambda表达式定义了一个匿名函数,并且可以捕获一定范围内的变量。语法形式如下:

[ capture ] ( params ) opt -> ret { body; };

1
capture:捕获列表
params:参数列表
opt:函数选项
ret:返回值类型
body:函数体
一个完整的lambda表达式是这样:

auto f = [](int a) -> int {return a + 1;};
cout << f(3) << endl;  //输出4

详细版本原文链接:https://blog.csdn.net/luoyayun361/article/details/123491439

直接定义一个线程对象:

};
int main(int argc, char* argv[])
{
    thread th(
        [](int i) {cout << "test lmbda " << i << endl; },
        123
    );
    return 0;
}


[](int i) {cout << "test lmbda " << i << endl; 相当于函数指针,指向一个打印test lmbda i的函数,i的值由第二个参数先拷贝,再传给这个指针指向的函数

用对象做为一个线程

class TestLambda
{
public:
    void Start()
    {
        thread th([this]() {cout << "name = " << name << endl; });
        th.join();
    }

    string name = "test lambda";
};
int main(int argc, char* argv[])
{
    TestLambda test;
    test.Start();
    return 0;
}

先创建一个对象,该对象有一个成员name
再调用该类的start方法,该方法将一个Lambda表达式包装成线程,并让该线程阻塞主线程,该Lambda表达式做为线程入口,捕获列表捕获了该对象的this指针,指明了打印哪个对象的name

二、caII once多线程函数调用,但函数只进入一次

比如多个线程都要初始化一个库,但只需要进入一次,可以使用个全局变量来进行判断,一旦有一个线程对其初始化了便将其设为false,其他线程便进不去了,但这样效率偏低,并且影响代码可读性,于是使用一个新的方法:

std::call_once():
该函数的第一个参数为标记,第二个参数是一个函数名。
功能:能够保证多线程调用函数func()时只被调用一次。具备互斥量的能力,而且比互斥量消耗的资源更少,更高效。
call_once()需要与一个标记结合使用,这个标记为std::once_flag;其中once_flag是一个数据结构,call_once()就是通过标记来决定函数是否执行,调用成功后,就把标记设置为一种已调用状态。

于是将想只调用一次的函数用call_once()进行包装

void SystemInit()
{
    cout << "Call SystemInit" << endl;
}

void SystemInitOne()
{
    static std::once_flag flag;
    std::call_once(flag, SystemInit);
}
int main(int argc, char* argv[])
{
    SystemInitOne();
    SystemInitOne();
    for (int i = 0; i < 3; i++)
    {
        thread th(SystemInitOne);
        th.detach();
    }
    getchar();
    return 0;
}

可以看到,虽然for遍历了三次,但只调用了一次:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/994124.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号