#include <thread>
#include <chrono>
#include <iostream>
#include <unistd.h>
void test()
{
for(int i=0;i<5;i++){
std::cout << "111111111" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "ending" << std::endl;
}
int main()
{
std::thread *th1 = new std::thread(test);
sleep(10);
if(th1->joinable())
{
std::cout << "can join" << std::endl;
th1->join();
}
return 0;
}
result:
root@ubuntu:~/test/thread # ./a.out
111111111
111111111
111111111
111111111
111111111
ending
can join
线程结束后依旧可联结
#include <thread>
#include <chrono>
#include <iostream>
#include <unistd.h>
void test()
{
for(int i=0;i<5;i++){
std::cout << "111111111" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "ending" << std::endl;
}
int main()
{
std::thread *th1 = new std::thread(test);
sleep(10);
if(th1->joinable())
{
if(th1->joinable())
{
th1->join();
std::cout << "can join" << std::endl;
}
//add
if(!th1->joinable())
{
std::cout << "cannot join" << std::endl;
}
}
return 0;
}
resuit:
root@ubuntu:~/test/thread # ./a.out
111111111
111111111
111111111
111111111
111111111
ending
can join
cannot join
join过的thread不再可联结
#include <thread>
#include <chrono>
#include <iostream>
#include <unistd.h>
void test()
{
for(int i=0;i<5;i++){
std::cout << "111111111" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "ending" << std::endl;
}
int main()
{
std::thread *th1 = new std::thread(test);
sleep(10);
//add
delete th1;
if(th1->joinable())
{
if(th1->joinable())
{
th1->join();
std::cout << "can join" << std::endl;
}
if(!th1->joinable())
{
std::cout << "cannot join" << std::endl;
}
}
return 0;
}
root@ubuntu:~/test/thread # ./a.out
111111111
111111111
111111111
111111111
111111111
ending
terminate called without an active exception
Aborted (core dumped)
std::thread对象析构时,会先判断joinable,如果可联结,则程序会直接终止)(terminate)
#include <thread>
#include <chrono>
#include <iostream>
#include <unistd.h>
void test()
{
for(int i=0;i<5;i++){
std::cout << "111111111" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "ending" << std::endl;
}
int main()
{
//std::shared_ptr<std::thread> th1(new std::thread(test),[](std::thread*p){delete p;}); //coredump
std::shared_ptr<std::thread> th1;
th1.reset(new std::thread(test),[](std::thread*p){std::cout << "not delete" << std::endl;});//normal
//add
sleep(2);
return 0;
}
root@ubuntu:~/test/thread # ./a.out
111111111
111111111
not delete
#include <thread>
2 #include <chrono>
3 #include <iostream>
4 #include <unistd.h>
5 void test()
6 {
7 for(int i=0;i<5;i++){
8 std::cout << "111111111" << std::endl;
9 std::this_thread::sleep_for(std::chrono::seconds(1));
10 }
11 std::cout << "ending" << std::endl;
12
13 }
14
15 int main()
16 {
17 std::thread *th1 = new std::thread(test);
18 th1->detach();
19 delete th1;
20 sleep(10);
21 return 0;
22 }
root@ubuntu:~/test/thread # $ ./a.out
111111111
111111111
111111111
111111111
111111111
ending
如果一个 std::thread 对象被析构,而且该线程是 detached 的,那么该线程会继续在后台运行,直到它完成或终止。在这种情况下,析构函数会释放 std::thread 对象所占用的资源,但是并不会等待该线程完成。
这就意味着,尽管 std::thread 对象已经被销毁,但是线程本身仍然在运行。因此,确保在销毁 std::thread 对象之前,该线程能够安全地运行完毕是很重要的。否则,如果线程正在访问已被销毁的对象或资源,可能会导致未定义行为或程序崩溃。
总结:
可联结性
一个 std::thread 对象只可能处于可联结或不可联结两种状态之一。即 std::thread 对象是否与某个有效的底层线程关联。
①.可联结:当线程可运行、已经运行或处于阻塞时是可联结的。但如果某个底层线程已经执行完任务,但是没有被 join 的话,该线程依然会被认为是一个活动的执行线程,仍然处于 joinable 状态。
②.不可联结:不带参构造的std::thread对象为不可联结,因为底层线程还没创建;已经移动的std::thread对象为不可联结;已经调用join或detach的对象为不可联结状态。
③.joinable():判断是否可以成功使用 join() 或者 detach() ,返回true 表示可以,否则返回 false。
std::thread 对象析构
std::thread 对象析构时,会先判断 joinable() ,如果可联结,则程序会直接被终止(terminate)。
因此,在创建 thread 对象以后,要在随后的某个地方显式地调用 join 或 detach 以便让 std::thread 处于不可联结状态。
若将线程detach,随时都可以delete it销毁线程,但貌似无法终止线程运行,否则必须join
后,即跑完线程才可以去delete it;