c++11提供了2个线程库来实现简单多线程。
future库包含所有需要的类模板;thread库提供用于启动执行的并发线程的支持。
本章介绍了线程类模板中的细节,并演示如何启动并同步线程。
1.线程类
Thread类定义了一个对象,它代表一个单独的执行线程。线程对象是可连接或不连接的。
一个可连接对象表示执行了一个独特的线程ID实际线程。非可连接对象表示执行的潜在线索。在一个线程对象的操作可以改变它的可连接/非可连接状态。
线程类模板定义在头文件:
#include <thread>
2.举例
下面的程序同时执行三项任务。它生成的执行两个线程的主线程,执行三项任务,并等待其主线程衍生的线程来完成。
在本实施例中,每个线程执行相同的任务(task)
// Thread Class
// thread.cpp
#include <iostream>
#include <thread>
void task() {
std::cout << "task says Hi" << std::endl;
}
int main() {
// spawn a child thread
std::thread t1(task);
// spawn another child thread
std::thread t2(task);
// continue executing the main thread
std::cout << "main says Hi" << std::endl;
// synchronize - IMPORTANT!
t2.join();
t1.join();
}
同步步骤是必要和重要的。如果我们忽略了join()衍生的线程的主线程,其结果将是不确定的。例如,主线程可以执行完它的工作和一个已经完成执行他们的任务衍生的线程或两者之前将控制返回给操作系统。 同步就是协同步调,按预定的先后次序进行运行。
3.成员函数
The member functions of the thread class template include:
- thread() noexcept - default - creates a not-joinable thread object (a potential thread of execution)
- thread(thread&& t) noexcept - moves the thread handler from thread t to the current thread object
- ~thread() - destroys the current thread object
- thread& operator=(thread&& t) noexcept - moves the thread handler from thread t to the current not-joinable object
- thread::id get_id() const - returns the unique identifier of the current thread object
- bool joinable() const noexcept - true if the current object represents an actual thread of execution
- void join() - returns once the current object has completed executing its task
- void detach() - detaches the current object from its parent object
- void swap(thread& t) - swaps the state of the current object with the state of object t
这个模板的拷贝构造和拷贝分配的成员函数将被删除。thread::id表示线程ID,类定义包括插入运算的
thread::id类型的右操作数的重载。
此模板的形式为:
template <typename Fn, typename... Args>
explicit thread(Fn&& f, Args&&... args);
4.线程ID
一个可连接线程对象的线程标识符是从执行线程的任务函数中访问。std::this_thread::get_id()返回线程ID。
下面的程序将启动10线程对象,并在标准输出上显示它们的标识符。该程序通过与一个函数作为其唯一的参数的地址构造函数模板创建每个对象:
// Thread Class - Thread Identifiers
// thread_id.cpp
#include <iostream>
#include <thread>
#include <vector>
const int NT = 10;
void task() {
std::cout << "Thread id = " <<
std::this_thread::get_id() << std::endl;
}
int main() {
// create a vector of threads
std::vector<std::thread> threads;
// launch execution of each thread
for (int i = 0; i < NT; i++)
threads.push_back(std::thread(task));
// synchronize their execution here
for (auto& thread : threads)
thread.join();
}
下面的程序使用模板化的构造,推出带参数的任务:
// Thread Class - Function with Arguments
// thread_id_arg.cpp
#include <iostream>
#include <thread>
#include <vector>
const int NT = 10;
void task(int i) {
std::cout << i << " Thread id = " <<
std::this_thread::get_id() << std::endl;
}
int main() {
// create a vector of not-joinable threads
std::vector<std::thread> threads;
// launch execution of each thread
for (int i = 0; i < NT; i++)
threads.push_back(std::thread(task, i));
// synchronize their execution here
for (auto& thread : threads)
thread.join();
}
在这个特殊的运行,从不同的线程的输出碰巧不交错。
5.函数对象
本实施例的功能的对象的版本如下:
// Thread Class - Function Object
// thread_id_fo.cpp
#include <iostream>
#include <thread>
#include <vector>
const int NT = 10;
class task {
public:
task(){}
void operator()(int i) {
std::cout << i << " Thread id = " <<
std::this_thread::get_id() << std::endl;
}
};
int main() {
// create a vector of not-joinable threads
std::vector<std::thread> threads;
// launch execution of each thread
for (int i = 0; i < NT; i++)
threads.push_back(std::thread(task(), i));
// synchronize their execution here
for (auto& thread : threads)
thread.join();
}
在这个特殊的运行,来自不同线程的输出恰好交错。
6.Lambda表达式
本实施例的lambda表达式版本更紧凑,并访问由索引值作为非本地变量:
// Thread Class - Lambda Expression
// thread_id_lambda.cpp
#include <iostream>
#include <thread>
#include <vector>
const int NT = 10;
int main() {
// create a vector of not-joinable threads
std::vector<std::thread> threads;
// launch the execution of each thread
for (int i = 0; i < NT; i++)
threads.push_back(std::thread([=]() {
std::cout << i << " Thread id = " <<
std::this_thread::get_id() << std::endl;
}));
// synchronize their execution here
for (auto& thread : threads)
thread.join();
}
注意,输出顺序不同于其它版本。