C++多线程库笔记2

future promise async

从父线程获取子线程的变量

假设有一个函数计算阶乘

void factorial(int N) {
	int res = 1;
	for (int i = N; i > 1; --i)
		res *= i;
	std::cout << "result is:" << res << std::endl;
}

int main() {
	std::thread t1(factorial,4);
	t1.join();
	return 0;
}

如果需要把结果返回,按照现有的知识,应该是用下面的方法

std::mutex mu;
std::condition_variable cond;
void factorial(int N,int& x) {
	int res = 1;
	for (int i = N; i > 1; --i)
		res *= i;
	std::cout << "result is:" << res << std::endl;
	std::unique_lock<std::mutex> locker(mu);
	x = res;
	locker.unlock();
	cond.notify_one();
}

int main() {
	int x=0;
	std::thread t1(factorial,4,std::ref(x));
	std::unique_lock<std::mutex> locker(mu);
	cond.wait(locker);
	std::cout << x << std::endl;
	t1.join();
	return 0;
}

这样还是很麻烦。标准库给出了解决方案,即使用std::async返回一个future变量。
get()方法会等待子线程结束后,返回子线程的结果。

#include <future>

int factorial(int N) {
	int res = 1;
	for (int i = N; i > 1; --i)
		res *= i;
	std::cout << "result is:" << res << std::endl;
	return res;
}

int main() {
	int x=0;
	std::future<int> fu = std::async(factorial, 4);
	x = fu.get();
	std::cout << x << std::endl;
	return 0;
}

get()方法只能调用一次
async不一定创建子线程,取决于第一个参数

std::async(std::launch::async|std::launch::deferred,factorial, 4);

不写的话,默认的是上面的方式。其中deferred参数不会创建子线程,而async方法会创建子线程

int factorial(int N) {
	int res = 1;
	for (int i = N; i > 1; --i)
		res *= i;
	std::cout << "result is: " << res <<" at "<<std::this_thread::get_id()<< std::endl;
	return res;
}

int main() {
	int x=0;
	std::future<int> fu = std::async(std::launch::deferred,factorial, 4);
	x = fu.get();
	std::cout << "x: " << x << " id: " << std::this_thread::get_id() << std::endl;
	return 0;
}

在这里插入图片描述

int factorial(int N) {
	int res = 1;
	for (int i = N; i > 1; --i)
		res *= i;
	std::cout << "result is: " << res <<" at "<<std::this_thread::get_id()<< std::endl;
	return res;
}

int main() {
	int x=0;
	std::future<int> fu = std::async(std::launch::async,factorial, 4);
	x = fu.get();
	std::cout << "x: " << x << " id: " << std::this_thread::get_id() << std::endl;
	return 0;
}

在这里插入图片描述

子线程获取父线程的变量

int factorial(std::future<int>& f) {
	int res = 1;
	int N = f.get();
	for (int i = N; i > 1; --i)
		res *= i;
	std::cout << "result is: " << res <<" at "<<std::this_thread::get_id()<< std::endl;
	return res;
}

int main() {
	int x=0;
	std::promise<int> p;
	std::future<int> f = p.get_future();
	std::future<int> fu = std::async(std::launch::async,factorial, std::ref(f));
	p.set_value(4);
	x = fu.get();
	std::cout << "x: " << x << " id: " << std::this_thread::get_id() << std::endl;
	return 0;
}

如果需要多个子线程获取同一个父线程中的变量,可以使用std::shared_future

std::mutex mu;
int factorial(std::shared_future<int> f) {
	int res = 1;
	int N = f.get();
	for (int i = N; i > 1; --i)
		res *= i;
	std::lock_guard<std::mutex> lock(mu);
	std::cout << "result is: " << res <<" at "<<std::this_thread::get_id()<< std::endl;
	return res;
}

int main() {
	int x=0;
	std::promise<int> p;
	std::future<int> f = p.get_future();
	std::shared_future<int> sf = f.share();
	std::future<int> fu1 = std::async(std::launch::async, factorial, sf);
	std::future<int> fu2 = std::async(std::launch::async, factorial, sf);
	std::future<int> fu3 = std::async(std::launch::async, factorial, sf);
	p.set_value(4);
	x = fu1.get();
	mu.lock();
	std::cout << "x: " << x << " id: " << std::this_thread::get_id() << std::endl;
	mu.unlock();
	x = fu2.get();
	mu.lock();
	std::cout << "x: " << x << " id: " << std::this_thread::get_id() << std::endl;
	mu.unlock();
	x = fu3.get();
	mu.lock();
	std::cout << "x: " << x << " id: " << std::this_thread::get_id() << std::endl;
	mu.unlock();
	return 0;
}

使用可调用对象

class A {
public:
	void f(int x,char c){}
	int operator()(int N) { return 0; }
};

void foo(int x){}
int main() {
	A a;
	std::thread t1(a, 6);//传递a的拷贝给子线程
	std::thread t2(std::ref(a), 6);//传递a的引用给子线程
	std::thread t3(std::move(a), 6);//传递a给子线程
	std::thread t4(A(), 6);//传递临时创建的A对象给子线程
	std::thread t5(foo, 6);//函数
	std::thread t6([](int x) {return x*x; }, 6);//lambda函数
	std::thread t7(&A::f, a, 8, 'w');//传递a的拷贝的成员函数给子线程
	std::thread t8(&A::f, &a, 8, 'w');//传递a的地址的成员函数给子线程
	t1.join();
	t2.join();
	t3.join();
	t4.join();
	t5.join();
	t6.join();
	t7.join();
	t8.join();
	return 0;
}

package_task

std::package_task包装一个可调用对象,并允许异步获取该可调用对象产生的结果。它将包装的可调用对象的结果传递给一个std::future对象(该对象通常在另一个线程中获取std::package_task的执行结果)

int factorial(int N) {
	int res = 1;
	for (int i = N; i > 1; --i)
		res *= i;
	std::cout << "result is:" << res << std::endl;
	return res;
}

std::deque<std::packaged_task<int()>> task_q;
std::mutex mu;
std::condition_variable cond;
void thread_1(){
	std::packaged_task<int()> t;
	{
		std::unique_lock<std::mutex> locker(mu);
		cond.wait(locker, []() {return !task_q.empty(); });
		t = std::move(task_q.front());
	}
	t();
}
int main() {
	std::thread t1(thread_1);
	std::packaged_task<int()> t(std::bind(factorial,4));
	std::future<int> ret = t.get_future();
	{
		std::unique_lock<std::mutex> locker(mu);
		task_q.push_back(std::move(t));
	}
	cond.notify_one();
	int value = ret.get();
	std::cout << value << std::endl;
	t1.join();
	return 0;
}

时间限制

int factorial(int N) {
	int res = 1;
	for (int i = N; i > 1; --i)
		res *= i;
	std::cout << "result is:" << res << std::endl;
	return res;
}

int main() {
	std::thread t1(factorial,4);
	//线程的时间限制
	std::this_thread::sleep_for(std::chrono::milliseconds(3));
	//上面的代码和下面的有相同的效果
	std::chrono::steady_clock::time_point tp = std::chrono::steady_clock::now() + std::chrono::milliseconds(3);
	std::this_thread::sleep_until(tp);
	t1.join();

	//锁的时间限制
	std::mutex mu;
	std::unique_lock<std::mutex> locker(mu);
	locker.try_lock_for(std::chrono::milliseconds(3));
	locker.try_lock_until(tp);

	//条件变量的时间限制
	std::condition_variable cond;
	cond.wait_for(locker, std::chrono::milliseconds(3));
	cond.wait_until(locker, tp);

	//future变量的时间限制
	std::promise<int> p;
	std::future<int> f = p.get_future();
	f.wait_for(std::chrono::milliseconds(3));
	f.wait_until(tp);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值