赞
踩
在 C++11 中不仅添加了线程类,还添加了一个关于线程的命名空间 std::this_thread,在这个命名空间中提供了四个公共的成员函数,通过这些成员函数就可以对当前线程进行相关的操作了
调用命名空间 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();
}
由于进程被创建后就有5种状态,所以同样地线程被创建后也有这五种状态:创建态,就绪态,运行态,阻塞态(挂起态),退出态(终止态)
线程和进程的执行有很多相似之处,在计算机中启动的多个线程都需要占用 CPU 资源,但是 CPU 的个数是有限的并且每个 CPU 在同一时间点不能同时处理多个任务。
命名空间 this_thread 中提供了一个休眠函数 sleep_for(),
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 时间片,抢到之后才会变成运行态,这时候程序才会继续向下运行。
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(); }
命名空间 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 时间片就可以执行相应的任务了。
参考:链接
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。