创建多线程 std::thread,join(),detach()
中文文档:原子操作std::atomic(可以无锁并发编程)
一、std::thread创建多线程
点击查看代码
#include <iostream>
#include <thread>
void fun1()
{
for (int i = 0; i < 10; i++)
{
std::cout << "1" << "2" << std::endl;
}
}
void fun2()
{
for (int i = 0; i < 10; i++)
{
std::cout << "3" << "4" << std::endl;
}
}
int main()
{
std::cout << "main start" << std::endl;
std::thread t1(fun1);
std::thread t2(fun2);
std::cout << "main end" << std::endl;
return 0;
}
可以看到,这样创建线程是有问题的,因为在创建了线程后线程开始执行,但是主线程main()
并没有停止脚步,仍然继续执行然后退出,此时线程对象还是joinable(可结合的)
的,线程仍然存在但指向它的线程对象已经销毁,所以会抛出异常。
二、如何保证子线程执行完了退出后再退出主线程呢?
1.使用join()
使用join接口可以解决上述问题,join的作用是让主线程等待直到该子线程执行结束(因此调用join会阻塞)。需要注意的是线程对象执行了join后就不再joinable
了,所以只能调用join()
一次。创建了线程之后并不是调用join或detach才会执行线程,也许调用join或detach之前线程已经执行完了。只要创建了线程对象(传递“函数名/可调用对象”作为参数的情况下),线程就开始执行(std::thread 有一个无参构造函数重载的版本,不会创建底层的线程,只是一个空的对象。)。
1)join()阻塞代码演示
点击查看代码
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
using namespace std;
void work()
{
this_thread::sleep_for(chrono::seconds(5));
}
int main()
{
clock_t start = clock();
vector<thread> t;
for (int i = 0; i < 5; i++)
{
t.emplace_back(thread(work));
//t[i].join(); //join放在这里程序运行时间为25s多一点
}
for (int i = 0; i < 5; i++)
{ //join放在这里程序运行时间为5s多一点
t[i].join(); //join会阻塞住,因此需要放在创建线程的循环外边才能达到多线程的效果
}
cout << clock() - start;
}
2)join()使用演示
点击查看代码
#include <iostream>
#include <thread>
void fun1()
{
for (int i = 0; i < 10; i++)
{
std::cout << "1" << "2" << std::endl;
}
}
void fun2()
{
for (int i = 0; i < 10; i++)
{
std::cout << "3" << "4" << std::endl;
}
}
int main()
{
std::cout << "main start" << std::endl;
std::thread t1(fun1);
std::thread t2(fun2);
std::cout << "***" << std::endl;
t1.join();
std::cout << "@@@" << std::endl;
t2.join();
std::cout << "main end" << std::endl;
//std::thread(fun1).join(); //和上面两句代码等价
return 0;
}
2. 使用detach()
detach是用来和线程对象分离的,这样线程可以独立地执行,不过这样由于没有thread对象指向该线程而失去了对它的控制,当对象析构时线程会继续在后台执行,但是当主程序退出时并不能保证线程能执行完。如果没有良好的控制机制或者这种后台线程比较重要,最好不用detach而应该使用join。
点击查看代码
#include <iostream>
#include <thread>
void fun1()
{
for (int i = 0; i < 10; i++)
{
std::cout << "1" << "2" << std::endl;
}
}
void fun2()
{
for (int i = 0; i < 10; i++)
{
std::cout << "3" << "4" << std::endl;
}
}
int main()
{
std::cout << "main start" << std::endl;
std::thread t1(fun1);
std::thread t2(fun2);
std::cout << "***" << std::endl;
t1.detach();
std::cout << "@@@" << std::endl;
t2.detach();
std::cout << "main end" << std::endl;
return 0;
}
由结果可见线程并没有执行完而退出