C++多线程笔记

线程创建

C++中对线程的创建都需要使用到库函数 <thread> ,但是线程的启动和使用可以通过 函数带有函数调用操作符的类实例 来进行。

函数式启动

函数名启动

无论是从何处启用多线程,都需要从C++线程库 <thread> 来开始一个线程,通过构造一个 std::thread 对象来启动,以下为最常见的线程创建方法:

1
2
void threadHello(void);
std::thread thread1(threadHello);

threadHello() 就是需要执行线程的函数;

std::thread 就是创建线程对象的类型;

thread1 就是被创造的线程对象,而 () 中则填写着被这个对象调用的函数。

函数启动

不同于通过函数名启动,函数启动时会带上其括号 () , 多个线程可被同时被一个线程对象启动。

式1:

1
std::thread my_thread((background_task()));

其中,通过第二层外层 () 将函数及其 () 括起来避免被解释为函数声明,即 my_thread( ( f() ) )

式2:

1
std::thread my_thread{ background_task() };

通过将 background() 包括在 {} 中,同样是将 background() 声明为一个变量的方法。

Lambda表达式

lambda表达式是在C++11以后的新特性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
```







## 类实例启动

`std::thread` 可以与任何 可调用(callable)类型一同工作,因此可以将一个带有函数调用操作符的类的实例传递给 `std::thread` 的构造函数来进行代替。

```c++
class background_task{
public:
void operator()() const{ //带有函数调用操作符
do_something();
do_something_else();
}
};

background_task threadF; //类实例

std::thread thread1(threadF); //线程调用该类实例

这种情况下,所提供的函数对象被赋值(copied)到属于新创建的执行线程的存储器中,并从那里调用。因此,副本与原版有着灯箱的行为,否则结果可能与预期不符。

函数调用操作符

1
2
3
4
5
struct AA{
void operator()(){
cout<<"aa";
}
}

AA()() 中,AA() 是构造函数,调用了() 操作符。