c++ 多线程: this_thread的使用

这篇具有很好参考价值的文章主要介绍了c++ 多线程: this_thread的使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在 C++11 中不仅添加了线程类,还添加了一个关于线程的命名空间 std::this_thread,在这个命名空间中提供了四个公共的成员函数,通过这些成员函数就可以对当前线程进行相关的操作了

1. get_id()

调用命名空间 std::this_thread 中的 get_id() 方法可以得到当前线程的线程 ID,函数原型如下:

thread::id get_id() noexcept;

关于函数使用对应的示例代码如下:

#include <iostream>
#include <thread>
using namespace std;

void func()
{
    cout << "子线程: " << this_thread::get_id() << endl;
}

int main()
{
    cout << "主线程: " << this_thread::get_id() << endl;
    thread t(func);
    t.join();
}

程序启动,开始执行 main() 函数,此时只有一个线程也就是主线程。当创建了子线程对象 t 之后,指定的函数 func() 会在子线程中执行,这时通过调用 this_thread::get_id() 就可以得到当前线程的线程 ID 了。

2. sleep_for()

同样地线程被创建后也有这五种状态:创建态,就绪态,运行态,阻塞态(挂起态),退出态(终止态) ,关于状态之间的转换是一样的,请参考进程,在此不再过多的赘述。

线程和进程的执行有很多相似之处,在计算机中启动的多个线程都需要占用 CPU 资源,但是 CPU 的个数是有限的并且每个 CPU 在同一时间点不能同时处理多个任务。·为了能够实现并发处理,多个线程都是分时复用CPU时间片,快速的交替处理各个线程中的任务·。因此多个线程之间需要争抢CPU时间片,抢到了就执行,抢不到则无法执行(因为默认所有的线程优先级都相同,内核也会从中调度,不会出现某个线程永远抢不到 CPU 时间片的情况)。

命名空间 this_thread 中提供了一个休眠函数 sleep_for(),调用这个函数的线程会马上从运行态变成阻塞态并在这种状态下休眠一定的时长,因为阻塞态的线程已经让出了 CPU 资源,代码也不会被执行,所以线程休眠过程中对 CPU 来说没有任何负担。这个函数是函数原型如下,参数需要指定一个休眠时长,是一个时间段:

template <class Rep, class Period>
void sleep_for (const chrono::duration<Rep,Period>& rel_time);

示例程序如下:

#include <iostream>
#include <thread>
#include <chrono>
using namespace std;

void func()
{
    for (int i = 0; i < 10; ++i)
    {
        this_thread::sleep_for(chrono::seconds(1));
        cout << "子线程: " << this_thread::get_id() << ", i = " << i << endl;
    }
}

int main()
{
    thread t(func);
    t.join();
}

在 func() 函数的 for 循环中使用了 this_thread::sleep_for(chrono::seconds(1)); 之后,每循环一次程序都会阻塞 1 秒钟,也就是说每隔 1 秒才会进行一次输出。需要注意的是:程序休眠完成之后,会从阻塞态重新变成就绪态,就绪态的线程需要再次争抢 CPU 时间片,抢到之后才会变成运行态,这时候程序才会继续向下运行

3. sleep_until()

命名空间 this_thread 中提供了另一个休眠函数 sleep_until(),和 sleep_for() 不同的是它的参数类型不一样

  • sleep_until():指定线程阻塞到某一个指定的时间点 time_point类型,之后解除阻塞
  • sleep_for():指定线程阻塞一定的时间长度 duration 类型,之后解除阻塞

该函数的函数原型如下:

template <class Clock, class Duration>
void sleep_until (const chrono::time_point<Clock,Duration>& abs_time);

示例程序如下:

#include <iostream>
#include <thread>
#include <chrono>
using namespace std;

void func()
{
    for (int i = 0; i < 10; ++i)
    {
        // 获取当前系统时间点
        auto now = chrono::system_clock::now();
        // 时间间隔为2s
        chrono::seconds sec(2);
        // 当前时间点之后休眠两秒
        this_thread::sleep_until(now + sec);
        cout << "子线程: " << this_thread::get_id() << ", i = " << i << endl;
    }
}

int main()
{
    thread t(func);
    t.join();
}

sleep_until() 和 sleep_for() 函数的功能是一样的,只不过前者是基于时间点去阻塞线程,后者是基于时间段去阻塞线程,项目开发过程中根据实际情况选择最优的解决方案即可。

4. yield()

命名空间 this_thread 中提供了一个非常绅士的函数 yield(),在线程中调用这个函数之后,处于运行态的线程会主动让出自己已经抢到的 CPU 时间片,最终变为就绪态,这样其它的线程就有更大的概率能够抢到 CPU 时间片了。使用这个函数的时候需要注意一点,线程调用了 yield () 之后会主动放弃 CPU 资源但是这个变为就绪态的线程会马上参与到下一轮 CPU 的抢夺战中,不排除它能继续抢到 CPU 时间片的情况,这是概率问题。

void yield() noexcept;

函数对应的示例程序如下:

#include <iostream>
#include <thread>
using namespace std;

void func()
{
    for (int i = 0; i < 100000000000; ++i)
    {
        cout << "子线程: " << this_thread::get_id() << ", i = " << i << endl;
        this_thread::yield();
    }
}

int main()
{
    thread t(func);
    thread t1(func);
    t.join();
    t1.join();
}

在上面的程序中,执行 func() 中的 for 循环会占用大量的时间,在极端情况下,如果当前线程占用 CPU 资源不释放就会导致其他线程中的任务无法被处理,或者该线程每次都能抢到 CPU 时间片,导致其他线程中的任务没有机会被执行。解决方案就是每执行一次循环,让该线程主动放弃 CPU 资源,重新和其他线程再次抢夺 CPU 时间片,如果其他线程抢到了 CPU 时间片就可以执行相应的任务了。

结论:
std::this_thread::yield() 的目的是避免一个线程长时间占用CPU资源,从而导致多线程处理性能下降
std::this_thread::yield() 是让当前线程主动放弃了当前自己抢到的CPU资源,但是在下一轮还会继续抢文章来源地址https://www.toymoban.com/news/detail-510943.html

到了这里,关于c++ 多线程: this_thread的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++11线程池和Linux C++线程对比使用

    2024年02月09日
    浏览(29)
  • Java多线程---线程的创建(Thread类的基本使用)

    本文主要介绍Java多线程的相关知识, Thread的创建, 常用方法的介绍和使用, 线程状态等. 文章目录 前言 一. 线程和Thread类 1. 线程和Thread类 1.1 Thread类的构造方法 1.2 启用线程的相关方法 2. 创建第一个Java多线程程序 3. 使用Runnable对象创建线程 4. 使用内部类创建线程 5. 使用Lamba

    2024年02月03日
    浏览(31)
  • 多线程系列(二) -Thread类使用详解

    在之前的文章中,我们简单的介绍了线程诞生的意义和基本概念,采用多线程的编程方式,能充分利用 CPU 资源,显著的提升程序的执行效率。 其中 java.lang.Thread 是 Java 实现多线程编程最核心的类,学习 Thread 类中的方法,是学习多线程的第一步。 下面我们就一起来看看,创

    2024年02月19日
    浏览(38)
  • 单元测试使用Thread.sleep()后线程直接停止

    单元测试中测试多线程,使用sleep()阻塞线程,但是运行后发现Thread.sleep()后的代码不执行,直接退出了线程。 在单元测试中,如果子线程处于阻塞、死亡状态时,单元测试会立刻停止所有子线程。 如下图,不会输出running

    2024年02月13日
    浏览(33)
  • 37.Python从入门到精通—Python3 多线程 线程模块 使用 threading 模块创建线程

    在Python 3中,线程模块已被重命名为_thread,同时还引入了更高级别的 threading 模块,它允许创建线程对象并提供了更多的方法来控制线程的行为。 以下是一个简单的示例,演示如何使用 threading 模块创建并启动线程: 在这个例子中,我们创建了一个名为 print_numbers 的函数,它

    2024年04月26日
    浏览(33)
  • Python 线程池 (thread pool) 创建及使用 + 实例代码

    首先线程和线程池不管在哪个语言里面,理论都是通用的。对于开发来说,解决高并发问题离不开对多个线程处理。我们先从线程到线程池,从每个线程的运行到多个线程并行,再到线程池管理。由浅入深的理解如何在实际开发中,使用线程池来提高处理线程的效率。 线程(

    2024年02月05日
    浏览(37)
  • 【Java中的Thread线程的简单方法介绍和使用详细分析】

    提示:若对Thread没有基本的了解,可以先阅读以下文章,同时部分的方法已经在如下两篇文章中介绍过了,本文不再重复介绍!! 【Java中Tread和Runnable创建新的线程的使用方法】 【Java中的Thread线程的七种属性的使用和分析】 提示:以下是本篇文章正文内容,下面案例可供参

    2024年02月15日
    浏览(30)
  • 【C++】—— C++11之线程库

    前言: 在本期,我将给大家介绍的是 C++11 中新引进的知识,即关于 线程库 的相关知识。 目录 (一)线程库的介绍 1、线程库的由来 2、线程库的简单介绍 (二)线程函数参数 (三)原子性操作库 (四)lock_guard与unique_lock 1、mutex的种类 2、lock_guard 3、unique_lock (五)condi

    2024年02月11日
    浏览(26)
  • JAVA深化篇_29—— 线程使用之线程联合以及Thread类中的其他常用方法【附有详细说明及代码案例】

    线程联合 当前线程邀请调用方法的线程优先执行,在调用方法的线程执行结束之前,当前线程不能再次执行。线程A在运行期间,可以调用线程B的join()方法,让线程B和线程A联合。这样,线程A就必须等待线程B执行完毕后,才能继续执行。 join方法的使用 join()方法就是指调用该

    2024年02月05日
    浏览(36)
  • 【C++】C++11:线程库和包装器

    C++11最后一篇文章 文章目录 前言 一、线程库 二、包装器和绑定 总结 上一篇文章中我们详细讲解了lambda表达式的使用,我们今天所用的线程相关的知识会大量的用到lambda表达式,所以对lambda表达式还模糊不清的可以先将上一篇文章看明白。 一、线程库 在 C++11 之前,涉及到

    2024年02月10日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包