std::jthread与std::thread区别

简介: std::jthread是C++20新引入的线程类,与 std::thread 类似,或者说,jthread是对thread进一步的封装,功能更强大。

std::jthread是C++20新引入的线程类,与 std::thread 类似,或者说,jthread是对thread进一步的封装,功能更强大。


std::jthread的j实际上是joining的缩写,众所周知,std::thread在其生命周期结束时调用join()(让主线程等待该子线程完成,然后主线程再继续执行,对于不会停止的线程,不要使用join(),防止阻塞其他线程),或调用detach()(调用detach()进行线程分离,使其不影响其他线程运行,比如一个线程中无限循环执行的场景下,需要detach())。如果join()和detach()都没有被调用,析构函数将立即导致程序异常终止。C++20引入的std::jthread得以解决这个问题,std::jthread对象被析构时,会自动调用join(),等待执行流结束。


此外,std::jthread支持外部请求中止操作,调用join()后可能需要等待很长时间,甚至是永远等待。std::jthread除了提供std::stop_token能够主动取消或停止正在执行的线程,还增加了std::stop_callback允许在停止线程操作时调用一组回调函数。


来看看cpprefercence关于std::jthread::~jthread的解释:

std::jthread::~jthread
Destroys the jthread object.
If *this has an associated thread (joinable() == true), calls request_stop() and then join().

Notes

The request_stop() has no effect if the jthread was previously requested to stop.


A jthread object does not have an associated thread after


  • it was default-constructed
  • it was moved from
  • join() has been called
  • detach() has been called


If join() throws an exception (e.g. because deadlock is detected), std::terminate() may be called.


关于std::jthread::join的作用:阻塞当前线程直至 *this 所标识的线程结束其执行。


看例程:

#include <iostream>
#include <thread>
#include <chrono>
void foo()
{
    // 模拟耗费大量资源的操作
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
void bar()
{
    // 模拟耗费大量资源的操作
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
    std::cout << "starting first helper...\n";
    std::jthread helper1(foo);
    std::cout << "starting second helper...\n";
    std::jthread helper2(bar);
    std::cout << "waiting for helpers to finish..." << std::endl;
    helper1.join();
    helper2.join();
    std::cout << "done!\n";
}

输出结果如下:

starting first helper...
starting second helper...
waiting for helpers to finish...
done!

std::jthread::joinable,主要是用来检查 std::jthread 对象是否标识活跃的执行线程,直接看cpprefercence相关例程:

#include <iostream>
#include <thread>
#include <chrono>
void foo()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
    std::jthread t;
    std::cout << "before starting, joinable: " << std::boolalpha << t.joinable()
              << '\n';
    t = std::thread(foo);
    std::cout << "after starting, joinable: " << t.joinable() 
              << '\n';
    t.join();
    std::cout << "after joining, joinable: " << t.joinable() 
              << '\n';
}

输出结果如下:

before starting, joinable: false
after starting, joinable: true
after joining, joinable: false

可知如果 jthread 对象标识活跃的执行线程则为 true ,否则为 false 。

相关文章
|
2月前
|
存储 前端开发 算法
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析(一)
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析
49 0
|
8月前
std::atomic和std::mutex区别
模板类std::atomic是C++11提供的原子操作类型,头文件 #include<atomic>。在多线程调用下,利用std::atomic可实现数据结构的无锁设计。
|
2月前
|
存储 并行计算 Java
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析(二)
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析
67 0
|
2月前
|
算法 API 调度
深入探索:在std::thread中创建并管理QEventLoop的全面指南(一)
深入探索:在std::thread中创建并管理QEventLoop的全面指南
41 1
|
2月前
|
存储 设计模式 前端开发
【C++并发编程】std::future、std::async、std::packaged_task与std::promise的深度探索(二)
【C++并发编程】std::future、std::async、std::packaged_task与std::promise的深度探索
30 0
|
2月前
|
存储 前端开发 安全
【C++并发编程】std::future、std::async、std::packaged_task与std::promise的深度探索(三)
【C++并发编程】std::future、std::async、std::packaged_task与std::promise的深度探索
27 0
|
2月前
|
并行计算 前端开发 安全
【C++并发编程】std::future、std::async、std::packaged_task与std::promise的深度探索(一)
【C++并发编程】std::future、std::async、std::packaged_task与std::promise的深度探索
67 0
|
2月前
|
存储 安全 调度
深入探索:在std::thread中创建并管理QEventLoop的全面指南(二)
深入探索:在std::thread中创建并管理QEventLoop的全面指南
27 2
|
2月前
|
存储 C语言 C++
std::atomic 相关接口(来自cppreference.com)
std::atomic 相关接口(来自cppreference.com)
25 0
|
4月前
|
安全 C++
C++ std::thread::detch函数之遇坑记录
调用thread::detch后,程序有可能会在当前调用函数执行完之后才去构造实参对象
16 0
C++ std::thread::detch函数之遇坑记录