C++ マルチスレッド 03 ラムダ式と caII 1 回

1.スレッドエントリとしてのラムダ式

ラムダ (無名関数) 式は C++11 の最も重要な機能の 1 つです. ラムダは関数型プログラミングの概念に由来し、最新のプログラミング言語の機能でもあります.

利点は次のとおりです。

宣言型プログラミング スタイル: 対象の関数または関数オブジェクトをその場で匿名で定義します。これにより、読みやすさと保守性が向上します。
簡潔: 追加の名前付き関数または関数オブジェクトを記述する必要がないため、コードの拡張と関数の分散が回避されます。
柔軟性の向上: 機能クロージャを必要なときに必要な場所に実装します。
概念と基本的な使用方法
ラムダ式は無名関数を定義し、特定の範囲内の変数をキャプチャできます。構文は次のとおりです。

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

1
capture: キャプチャ リスト
params: パラメータ リスト
opt: 関数オプション
ret: 戻り値の型
body: 関数本体
完全なラムダ式は次のとおりです。

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; テスト lmbda i を出力する関数を指す関数ポインターと同等であり、i の値は最初に 2 番目のパラメーターによってコピーされます。 、そしてポインタが指すこの関数に渡されます

オブジェクトをスレッドとして使用する

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;
}

最初にオブジェクトを作成し、オブジェクトにはメンバー名があり
、次にクラスの開始メソッドを呼び出します.このメソッドはラムダ式をスレッドにラップし、スレッドブロックをメインスレッドにします.ラムダ式はスレッドエントリとして使用されます. 、およびキャプチャ リスト キャプチャ オブジェクトの this ポインタ。出力するオブジェクトの名前を示します。
ここに画像の説明を挿入

2. マルチスレッド関数呼び出しは 1 回だけですが、関数は 1 回だけ入ります。

たとえば、複数のスレッドがライブラリを初期化する必要がありますが、それらは一度だけ入る必要があります. グローバル変数を使用して判断できます. スレッドが初期化したら、それを false に設定すると、他のスレッドはそれに入ることができなくなります. . 効率が低く、コードの可読性に影響を与えるため、新しい方法が使用されます。

std::call_once():
この関数の最初のパラメーターはマーカーで、2 番目のパラメーターは関数名です。
機能: 複数のスレッドが関数 func() を呼び出したときに、関数 func() が 1 回だけ呼び出されるようにすることができます。ミューテックスの機能があり、ミューテックスよりもリソースの消費が少なく、効率的です。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;
}

3 回トラバースする場合でも、1 回だけ呼び出されることがわかります。
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_42567607/article/details/125464750