https://segmentfault.com/a/1190000040628584?utm_source=sf-similar-article
1 创建线程
C++11 之前原生不支持多线程,C++11起逐步引入了对线程的支持。
std::thread
在 <thread>
头文件中声明,因此使用 std::thread 时需要包含 <thread>
头文件。
#include <iostream>
#include <thread>
void func(int a) {
while (true) {
std::cout << "hello world" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 休眠50毫秒
}
}
int main() {
int n = 0;
std::thread t1(func, n);
return 0;
}
上述代码中我们创建了一个 thread 线程 t1, 让它调用函数 func,并为其传入函数参数 n。
❗️线程创建后即开始运行,不需要调用 run 之类的函数才能执行。
但我们发现程序运行没多久,就会报错,这是因为主线程 main 创建完子线程 t1 后没有任何代码,就退出了。而子线程 t1 还没有执行完毕,此时就会报错了。
解决方法:
1️⃣ 使用 join
函数
这样主线程 main 即使执行完成,也会一直等待 join 的子线程执行完毕,才会结束。
...
int main() {
int n = 0;
std::thread t1(func, n);
t1.join();
return 0;
}
2️⃣ 使用 detach
函数
该函数会将主线程和子线程完全分离开,二者不再有任何关系。主线程 main 创建完子线程 t1 后,执行后续代码,执行完毕就直接退出。
...
int main() {
int n = 0;
std::thread t1(func, n);
t1.detach();
return 0;
}
detach其实就是一个守护线程。
使用 detach() 时要注意访问数据的有效性,假如向子线程 t1 传入的参数是个指针/引用,在主线程 main 执行完毕退出后,指针指向的内容就会失效,而子线程中还在使用该指针,则会出现错误。
线程的入口函数 可以是:普通函数、类的静态/非静态成员函数、lambda 表达式。
1.1 其他操作
操作 | 功能 | 示例 |
---|---|---|
swap(std::thread& other) | 交换两个线程 | std::thread t1(func, n); std::thread t2(func, n); t1.swap(t2); |
get_id() | 返回线程 id | t1.get_id(); |
hardware_concurrency() | 返回硬件所实现支持最大并发线程数 (值不一定准确,只能做参考) |
t1.hardware_concurrency(); |
native_handle() | 返回操作系统支持的线程句柄 | t1.native_handle(); |
这些都是在创建子线程 t1 的主线程 main 中能操作的方法,若我要在子线程 t1 执行的函数 func 中获取这些数据,要如何调用?使用 std::this_thread
操作当前线程。
#include <iostream>
#include <thread>
void func(int a) {
while (true) {
std::cout << "thread_id = " << std::this_thread::get_id() << std::endl;
std::cout << "hardware_concurrency = " << std::this_thread::hardware_concurrency() << std::endl;
std::cout << "native_handle = " << std::this_thread::native_handle() << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 休眠50毫秒
}
}
int main() {
int n = 0;
std::thread t1(func, n);
return 0;
}
std::this_thread
还有其他的方法:
操作 | 功能 | 示例 |
---|---|---|
sleep_for() | 睡眠一段时间 | std::this_thread::sleep_for (std::chrono::seconds(1)); |
sleep_until() | 睡眠到一个绝对时间 | |
yield() | 当前线程放弃执行 操作系统调用另一线程继续执行 |
while (!ready) { // wait until main() sets ready... std::this_thread::yield(); } |
2 互斥量(mutex)
2.1 基础使用
#include <iostream>
#include <thread>
int global_veriable = 0;
void task() {
for (int i = 0; i < 1000; i++) {
global_veriable++;
global_veriable--;
}
}
int main() {
std::thread t1(task);
std::thread t2(task);
t1.join();
t2.join();
std::cout << "current value is " << global_veriable;
return 0;
}
看代码感觉 global_veritable 应该为 0,但是实际上可能每次运行都是不同的值。因为两个线程都会对该公共变量 global_veritable 进行读写访问。
多线程编程需考虑对公共资源的保护,否则涉及对公共资源访问的代码是不安全的。—— 互斥量(mutex)
std::mutex
对象提供了独占所有权的特性。在 <mutex>
头文件中声明,因此使用 std::mutex
时需要包含<mutex>
头文件。
现在,我们在
标签:std,include,int,lock,C++,并发,task,线程,多线程 From: https://www.cnblogs.com/angelia-wang/p/17354385.html