一 C++11多线程简介
C++11标准库会提供类thread(std::thread)。若要运行一个线程,可以创建一个类thread的实体,其初始参数为一个函数对象,以及该函数对象所需要的参数。通过成员函数std::thread::join()对线程会合的支持,一个线程可以暂停直到其它线程运行完毕。若有底层平台支持,成员函数std::thread::native_handle()将可提供对原生线程对象运行平台特定的操作。对于线程间的同步,标准库将会提供适当的互斥锁(像是std::mutex,std::recursive_mutex等等)和条件参数(std::condition_variable和std::condition_variable_any)。前述同步机制将会以RAII锁(std::lock_guard和std::unique_lock)和锁相关算法的方式呈现,以方便程序员使用。
对于要求高性能,或是极底层的工作,有时或甚至是必须的,我们希望线程间的通信能避免互斥锁使用上的开销。以原子操作来访问内存可以达成此目的。针对不同情况,我们可以通过显性的内存屏障改变该访问内存动作的可见性。
对于线程间异步的传输,C++11标准库加入了以及std::packaged_task用来包装一个会传回异步结果的函数调用。因为缺少结合数个future的功能,和无法判定一组promise集合中的某一个promise是否完成,futures此一提案因此而受到了批评。
更高级的线程支持,如线程池,已经决定留待在未来的TechnicalReport加入此类支持。更高级的线程支持不会是C++11的一部分,但设想是其最终实现将创建在目前已有的线程支持之上。
std::async提供了一个简便方法以用来运行线程,并将线程绑定在std::future。用户可以选择一个工作是要多个线程上异步的运行,或是在一个线程上运行并等待其所需要的数据。默认的情况,实现可以根据底层硬件选择前面两个选项的其中之一。另外在较简单的使用情形下,实现也可以利用线程池提供支持。
?
二 简单std::thread的使用
?
#include
#include
using namespace std; void myFirstThread() { cout << "Hello thread" << endl; } int main() { thread myThread(myFirstThread); myThread.join(); return 0; }
?
?
三 std::thread类构造函数函数简介
?
std::thread构造
1 默认构造,创建一个空的thread对象,以下为默认构造函数声明:
thread() noexcept;
2 拷贝构造 copy-delete(thread对象不可拷贝构造):
thread (const thread&) = delete;
3 初始化构造,创建thread对象,该对象可被joinable,线程会调用fn函数,参数由args给出,下边为初始化构造 函数声明:
template
explicit thread (Fn&& fn,Args&&... args);
4 移动构造 move,此构造函数调用成功之后,x不代表任何thread可执行对象。
thread (thread&& x) noexcept;
注意:可被joinable的thread对象必须在他们销毁之前被主线程join或者将之设置为detached。
std::thread各种构造函数示例如下:
?
#include
#include
using namespace std; void myFirstThreadTask(int num) { for (int i = 0; i < 10; ++i) { cout << "myFirstThreadTask's num = " << num++ << endl; this_thread::sleep_for(chrono::milliseconds(10)); } } void mySecondThreadTask(int &num) { for (int i = 0; i < 10; ++i) { cout << "mySecondThreadTask's num = " << num++ << endl; this_thread::sleep_for(std::chrono::milliseconds(10)); } } int _tmain(int argc, _TCHAR* argv[]) { int n = 5; thread myThread0;//myThread1为一个空线程,不代表任何可执行对象 //myThread1与myFirstThreadTask函数绑定,n为其按值传递参数 thread myThread1(myFirstThreadTask,n); //myThread2与mySecondThreadTask函数绑定,n为其引用传递参数 thread myThread2(mySecondThreadTask,std::ref(n)); myThread1.join(); myThread2.join(); n++; //现在myThread2不代表任何可执行对象,myThread3与mySecondThreadTask函数绑定 thread myThread3(std::move(myThread2)); //myThread3.join(); return 0; }
?