天天看点

C++11 多线程学习----std::thread类的简单使用

一 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 <iostream>
#include <thread>
 
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 <class Fn, class... Args>

explicit thread (Fn&& fn,Args&&... args);

4移动构造 move,此构造函数调用成功之后,x不代表任何thread可执行对象。

thread (thread&& x) noexcept;

注意:可被joinable的thread对象必须在他们销毁之前被主线程join或者将之设置为detached。      
std::thread各种构造函数示例如下:      
#include <iostream>
#include <thread>

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 main(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));

	//现在myThread2不代表任何可执行对象,myThread3与mySecondThreadTask函数绑定
	thread myThread3(std::move(myThread2));

	myThread1.join();
	myThread3.join();


	
	//myThread3.join();
	return 0;
}