C++多线程与并发

时间:2019-02-14
本文章向大家介绍C++多线程与并发,主要包括C++多线程与并发使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

常见概念

进程:程序在一个数据集合上的一次运行过程。一个程序在不同数据集合上运行,乃至一个程序在同样数据集合上面的多次运行都是不同的进程。进程是独立的,表现在内存空间、上下文环境

线程:线程是进程中的实体,是被系统独立调度和执行的基本单位。

任务:用户在一次接解题或一个事务处理过程中要求计算机系统所做工作的集合。它包括用户程序、所需的数据集合及控制命令。作业是由一系列有序的步骤组成的。

C++11并发

线程使用

包含头文件:

#include<thread>

处理:

template<class _Fn,
	class... _Args,
	class = enable_if_t<!is_same_v<remove_cv_t<remove_reference_t<_Fn>>, thread>>>
	explicit thread(_Fn&& _Fx, _Args&&... _Ax);

thread(thread&& _Other) noexcept;
thread(const thread&) = delete;

两种方式创建线程:第一种为创建线程后执行函数,第二种通过已创建线程来创建线程,其中第二种被禁止;

int n{ 0 };
void f(int x,int y)
{
	std::cout << x << "  " << y;
	while (true)
	{
		//m.lock();
		std::cout << "hello" << " "<<n<< std::endl;
		n += 10;
		//m.unlock();
	}
		
}

int main()
{
	int x{21};
	int y{32};
	std::thread th{f,x,y};
	th.join();
	return 0;
}

数据同步:

实现数据同步的方式有多种,其中最常见的为使用critical section,mutex,event等这几种方式。

使用mutex时需要包含头文件:

#include<mutex>

处理:

std::mutex m;
std::unique_lock lk(m);
lk.lock();

lk.unlock();

任务通信

标准库提供了一些特性,允许程序员在抽象的任务层(工作并发执行)进行操作,而不是在底层的线程和锁的层次直接进行操作。

promise和future

  1. future和promise用来从一个独立线程上创建出的任务返回结果;
  2. packaged_task是帮助启动任务以及连接任务返回的结果的机制;
  3. asyunc以非常类似调用函数的方式启动一个任务。

包含头文件:

#include<future>

处理:

future和promise允许在两个任务间进行传输值,而无需显示使用锁–系统高效地实现了数据传输。

std::future<int> fx;
std::promise<int> px;

void fun(std::promise<int>& px>
{
	try{
		int x{21};
		px.set_value(x);
		}
	catch(...)
	{}
}

fx=px.get_future();

int x = fx.get();

async

处理:

double comp4(vector& v)
{

if(v.size()<10000) return accumulate(v.begin(),v.end(),0.0);

auto first = &v[0];
auto size =v.size();

auto as0=std::async(accumulate(first,first+size/3,0.0));
auto as1 = std::async(accumulate(first+size/3,first+size*2/3,0.0);
auto as2 = std::async(accumulate(first+size*2/3,first+size,0.0);

return as0.get()+as1.get()+as2.get();

}

packaged_task

处理:

double accum(double* begin, double* end, double init)
{
	return accumulate(begin,end,init);
}

double comp2(std::vector<double>& v)
{
	using Task_Type=double(double*, double*, double);
	packaged_task<Task_Type> pt0{accum};
	packaged_task<Task_Type> pt2{accum};

	future<double> f0{pt0.get_future()};
	future<double> f1{pt1.get_future()};

	double* first = &v[0];
	thread t1{move(pt0),first,first+v.size()/2,0};
	thread t2{move(pt1),first+v.size()/2,fisrt+v.size(),0};

	return f0.get()+f1.get();
}