(九)QT专题-在QT中使用C++11线程类
2023-02-16 本文已影响0人
GoodTekken
前面讲的线程利用的是POSIX线程库,这是传统C/C++程序员使用线程的方式。在C++11中,提供了语言层面使用线程的方式。最令人兴奋的是,QT已经内置支持C++11,比如新建一个控制台项目后,可以在项目配置文件(.pro)中看到下面这一句:
CONFIG += c++11 console
这说明Qt已经完全从内部支持C++11。
C++11新标准中引入了如下5个头文件来支持多线程编程。
- atomic:该头文件主要声明了两个类,即std::atomic和std::atomic_flag,另外还声明了一套C语言风格的原子类型和与C语言兼容的原子操作函数。
- thread:该头文件主要声明了std::thread类,另外std::this_thread命名空间也在该头文件中。
- mutex:该头文件主要声明了与互斥量(mutex)相关的类,包括std::mutex系列类、std::lock_guard、std::unique_lock以及其他的类型和函数。
- condition_variable:该头文件主要声明了与条件变量相关的类,包括std::condition_variable和std::condition_variable_any。
- future:该头文件主要声明了std::promise和std::package_task这两个Provider类,以及std::future和std::shared_future这两个Future类,另外还有一些与之相关的类型和函数,比如std::async函数。
1.线程的创建
#include <thread>
std::thread threads[5];
for(int i = 0;i<5;i++)
{
thread[i] = std::thread(thfunc,i+1);
}
for(auto& t : threads) //等待每个线程结束
{
t.join();
}
2.线程的创建
//page443
thread t1(fun,ref(n));
thread t2(move(t1));
从这个例子可以看出,t1并不会执行,执行的是t2,因为t1的线程函数移给t2了。
3.线程的标识符
其中,id是线程标识符的类型,是thread类的成员,用来唯一标识某个线程。
线程id获取:=> this_thread::get_id()
thread::id main_thread_id = this_thread::get_id();
4.当前线程this_thread
在实际的线程开发中,经常需要访问当前线程。C++11提供了一个命名空间this_thread来引用当前线程,该命名空间集合了4个有用的函数:get_id()、yield()、sleep_until()、sleep_for()。
函数get_id()和thread类的成员函数get_id()是同一个意思,都是用来获取线程id的。
5.让出CPU时间
void yield();
atomic<bool> ready(false); //定义全局变量
atomic用来定义在全局变量ready上的操作都是原子操作。原子操作表示在多个线程访问同一个全局资源的时候,确保所有其他的线程都不在同一时间内访问这个相同的全局资源,也就是确保在同一时刻只有唯一的线程对这个全局资源进行访问。这有点类似于互斥对象对共享资源访问的保护,但是原子操作更加接近底层,因而效率更高。
Page446
6.让线程暂停一段时间
函数sleep_until()和sleep_for()用来阻塞线程,会让线程暂停执行一段时间。
template <class Clock, class Duration>
void sleep_until(const chrono::time_point<Clock,Duration>& abs_time);
template <class Rep, class Period>
void sleep_for(const chrono::duration<Rep,Period>& rel_time);
std::this_thread::sleep_for(std::chrono::seconds(1)); //暂停一秒