C++多线程
本文最后更新于:2023年7月16日 晚上
使用线程需要include<thread>
线程启动
构造thread对象,可填以下参数:
- 使用lambda表达式
- 使用函数对象,需要注意传递形式,直接传入
background_task()
将出现错误(传递临时变量将被认为是函数声明) - 有函数调用符类型的实例
- 函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#include<iostream>
#include<thread>
using namespace std;
class background_task
{
public:
void operator()() const
{
cout << "nihao" << endl;
cout << "hello" << endl;
}
};
void do_some_work(){
cout<<"do_some_work"<<endl;
}
int main() {
background_task f;
// 下述四种选择一种即可
// lambda表达式
thread my_thread([] {
cout << "nihao" << endl;
cout << "hello2" << endl;
});
// 函数
void do_some_work();
thread my_thread(do_some_work);
// 有函数调用符类型的实例
background_task f;
thread my_thread(f);
// 函数对象
thread my_thread((background_task()));
thread my_thread{background_task()};
my_thread.join();
return 0;
}
等待线程
使用join()
方法,清理线程相关的存储部分,thread
对象将不再与已经完成的线程有任何关联。故只能对一个线程使用一次join()
,可使用joinable()
判断某个线程是否使用过join()
参数传递
- 传递引用。在线程中直接传递引用,
thread
的构造函数会无视函数期待的参数类型,并盲目的拷贝已提供的变量,传递给函数的参数是data
变量内部拷贝的引用,而非数据本身1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include<iostream>
#include<thread>
using namespace std;
typedef int widget_id;
typedef int widget_data;
void update_data_for_widget(widget_id w, widget_data& data) {
data = 4;
}
void oops_again(widget_id w)
{
widget_data data=10;
// 使用ref将参数转换成引用的形式,从而可将线程的调用改为以下形式:
// thread t(update_data_for_widget, w, ref(data));
thread t(update_data_for_widget, w, data);//直接使用该语句将会报错
cout << " current data: " << data << endl;;
t.join();
cout << " after thread data: " << data << endl;
}
int main() {
oops_again(5);
}
其他
获取线程id和CPU最多的核芯
1 |
|
互斥量
需要#include<metux>
,通过实例化metux对象创建互斥量,调用成员函数lock()和unlock()进行上锁和解锁(注意每个函数出口都要unlock()包括异常退出);也可以使用模板类lock_guard,在构造函数中提供已锁的变量在析构时解锁
metux的示例程序,在两个函数中对数据some_list的访问是互斥的,当函数返回的是保护数据的指针或引用时,会破坏对数据的保护,因此切勿将受保护数据的指针或引用传递到互斥锁作用域之外
1 |
|
C++多线程
https://danmoliuhen.github.io./2023/02/19/C++多线程/