C++ multithreading 03 Lambda expression and caII once

1. Lambda expression as thread entry

Lambda (anonymous function) expression is one of the most important features of C++11. Lambda comes from the concept of functional programming and is also a feature of modern programming languages.

The advantages are as follows:

Declarative programming style: define the target function or function object anonymously in place, which has better readability and maintainability.
Concise: There is no need to write an additional named function or function object, avoiding code expansion and function dispersion.
More flexible: Implement functional closures when and where you need them.
Concept and basic usage
lambda expression defines an anonymous function, and can capture variables within a certain range. The syntax is as follows:

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

1
capture: capture list
params: parameter list
opt: function option
ret: return value type
body: function body
A complete lambda expression is as follows:

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

Detailed version of the original link: https://blog.csdn.net/luoyayun361/article/details/123491439

Define a thread object directly:

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

insert image description here
[](int i) {cout << "test lmbda " << i << endl; It is equivalent to a function pointer, pointing to a function that prints test lmbda i, the value of i is first copied by the second parameter, and then passed to this function pointed to by pointer

Use an object as a thread

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

Create an object first, the object has a member name
, and then call the start method of the class. This method wraps a Lambda expression into a thread, and makes the thread block the main thread. The Lambda expression is used as the thread entry, and the capture list captures The this pointer of the object, indicating which object's name to print
insert image description here

2. caII once multi-threaded function call, but the function only enters once

For example, multiple threads need to initialize a library, but only need to enter it once, you can use a global variable to judge, once a thread initializes it, set it to false, and other threads cannot enter, but this The efficiency is low and affects the readability of the code, so a new method is used:

std::call_once():
The first parameter of this function is a marker, and the second parameter is a function name.
Function: It can ensure that the function func() is called only once when multiple threads call it. It has the ability of mutex, and consumes less resources than mutex, and is more efficient.
call_once() needs to be used in conjunction with a flag, which is std::once_flag ; where once_flag is a data structure, call_once() uses the flag to determine whether the function is executed. After the call is successful, set the flag to a called state.

So wrap the function that you want to call only once with 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;
}

It can be seen that although for traverses three times, it is only called once:
insert image description here

Guess you like

Origin blog.csdn.net/qq_42567607/article/details/125464750