mmxingye

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

03 | this_thread命名空间

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

get_id()


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

thread::id get_id() noexcept;

sleep_for()


为了能够实现并发处理,多个线程都是分时复用CPU时间片,快速的交替处理各个线程中的任务。因此多个线程之间需要争抢CPU时间片,抢到了就执行,抢不到则无法执行
(因为默认所有的线程优先级都相同,内核也会从中调度,不会出现某个线程永远抢不到 CPU 时间片的情况)。

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

template <class Rep, class Period>
void sleep_for (const chrono::duration<Rep,Period>& rel_time);
this_thread::sleep_for(chrono::seconds(1));//阻塞1s

sleep_until()


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

template <class Clock, class Duration>
void sleep_until (const chrono::time_point<Clock,Duration>& abs_time);
  • sleep_until():指定线程阻塞到某一个指定的时间点 time_point类型,之后解除阻塞
  • sleep_for():指定线程阻塞一定的时间长度 duration 类型,之后解除阻塞
#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();
}

yield()


使用这个函数的时候需要注意一点,线程调用了 yield () 之后会主动放弃 CPU 资源,但是这个变为就绪态的线程会马上参与到下一轮 CPU 的抢夺战中,不排除它能继续抢到 CPU 时间片的情况,这是概率问题。

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

#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://subingwen.cn/cpp/this_thread/#2-sleep-for

posted on   独立树  阅读(133)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示