转移线程的所有权

线程不能被拷贝,但是可以转移。在C++中,std::ifstream不能拷贝,但是可以转移(moveable),std::thread一样。

void some_function();
void some_other_funciton();
std::thread t1(some_function);//创建线程t1,运行some_function
std::thread t2=std::move(t1);//创建t2,t1所有权交给t2,这时t1不在和运行线程相关
t1=std::thread(some_other_funciton);//创建新线程,和t1关联。
std::thread t3;
t3=std::move(t2);//控制权交给t3
t1=std::move(t3);//控制权交给t1,这时t1运行的线程就会结束

函数返回值为线程

std::thread f()
{
	void some_function();
	return std::thread(some_function);
}
std::thread g()
{
	void some_other_function(int);
	std::thread t(some_other_function,42);
	return t;
}

如果函数的参数为线程,那么它只能接收值传递。

void f(std::thread t)
{
	void some_funtion();
	f(std::thread(some_function));
	std::thread t(some_function);
	f(std::move(t));
}

对象控制权的转移的一个用法是用thread_guard对象来管理thread对象的声明周期(RAII)。在创建thread_guard对象时拿到thread对象的控制权,在其析构函数调用join等待线程。thread对象不允许拷贝和复制,所以只有thread_guard有它的控制权,在thread_guard对象销毁时,会等待线程的结束。用一个类scoped_thread来表示:

class scoped_thread
{
	std::thread t;
public:
	explicit scoped_thread(std::thread t_)
		t(std::move(t_)
	{
		if(!t.joinable())
			throw std::logic_error("No thread");
	}
	~scoped_thread()
	{
		//析构函数调用join,等待线程结束
		t.join();
	}
	//禁用下面两个函数
	scoped_thread(scoped_thread const&)=delete;
	scoped_thread * operator=(scoped_thread const &)=delete;
};
struct func;
void f()
{
	int some_local_state;
	//直接传递了新创建的线程,没有命名变量
	scoped_thread t(std::thread(func(some_local_state)));

	do_something_in_current_thread();
}

线程控制权的转移使得可以使用线程对象容器。下面代码表示创建多个线程之后等待它们结束。

void do_work(unsigned id);

void f()
{
	std::vector<std::thread> threads;
	for(unsigned i=0;i<20;++i)
	{
		threads.push_back(std::thread(do_work,i));
	}
	//在每一个线程上调用join
	std::for_each(threads.begin(),threads.end(),std::mem_fn(&std::thread::join);
}

时间: 2024-11-08 19:31:15

转移线程的所有权的相关文章

[C++11 并发编程] 03 向线程传递参数

我们可以通过std::thread的构造函数向线程传递参数,但是默认情况下,这些参数的拷贝会被传递到线程内部,即使参数申明为引用,也是如此: void f(int i,std::string const& s); std::thread t(f,3,"hello"); 如上面例子所示,创建了一个线程关联到t,它会调用f(3, "hello"),虽然f的第二个参数类型为std::string,但是实际上字面量hello还是以char const *类型传递到线

并发编程(2)线程管理

一.启动线程 void do_something(); std::thread t(do_something); 注意t是创建的线程,do_something是函数对象,不要传入函数.提供的函数对象会复制到新线程的存储空间当中,函数对象的执行和调用都在线程的内存空间中进行. join(),detach() 二.线程传参 线程调用传参 void f(int i,std::string const& s); std::thread t(f,3,"hello"); 注意线程初始化不会

Windows Server 2012 R2 群集故障转移介绍

故障转移群集是一组相互独立的计算机,通过协同工作改善群集角色(以前也叫做群集的应用程序与服务)的可用性与扩展性.群集的服务器(叫做节点)通过物理线缆及软件连接在一起.如果一个或多个群集结点故障,其他节点可继续提供服务(这一过程叫做故障转移).此外群集角色可通过主动监控以验证节点是否正常工作.如果没能正常工作,则会重启动或转移到其他节点.故障转移群集还提供了群集共享卷(CSV)功能,能为群集角色提供一致的分布式名称空间,供群集节点访问所有节点的共享存储.通过使用故障转移群集功能,用户感受到的服务中

并发编程—— 任务取消 之 停止基于线程的服务

Java并发编程实践 目录 并发编程—— ConcurrentHashMap 并发编程—— 阻塞队列和生产者-消费者模式 并发编程—— 闭锁CountDownLatch 与 栅栏CyclicBarrier 并发编程—— Callable和Future 并发编程—— CompletionService : Executor 和 BlockingQueue 并发编程—— 任务取消 并发编程—— 任务取消 之 中断 并发编程—— 任务取消 之 停止基于线程的服务 概述 第1 部分 问题描述 第2 部分

线程理解

同步队列转移 线程状态转移 原文地址:https://www.cnblogs.com/saiQsai/p/10359107.html

Google&#39;s C++ coding style

v0.2 - Last updated November 8, 2013 源自 Google's C++ coding style rev. 3.274 目录 由 DocToc生成     头文件        #define用法        前向声明        内联函数        -inl.h文件        函数参数顺序        include的命名和顺序    作用域        命名空间            未命名空间            命名空间       

Rust的“并发安全”设计

部分内容参考Aaron Turon的文章<Fearless Concurrency with Rust > 昨天发了一篇说异步IO和轻量级线程的文章,有人问我为什么不在后面补充一下rust的并发模型.其实rust并不存在一个独特的并发模型,但它从语言层面上提供了一整套机制来保证并发的安全,借助这套机制,你可以安全的实现很多并发模型,如消息传递式.共享状态式.无锁式和纯函数式.昨天晚上我在群里和人讨论有关设计的话题,我觉得一个好的设计应当有两方面表现,一方面是符合直觉,也就是各个方面保证一致性以

Google开发规范

v0.2 - Last updated November 8, 2013 源自 Google's C++ coding style rev. 3.274 目录 由 DocToc生成     头文件        #define用法        前向声明        内联函数        -inl.h文件        函数参数顺序        include的命名和顺序    作用域        命名空间            未命名空间            命名空间       

C++11 锁 lock

转自:https://www.cnblogs.com/diegodu/p/7099300.html 互斥(Mutex: Mutual Exclusion) 下面的代码中两个线程连续的往int_set中插入多个随机产生的整数. 1234567891011121314 std::set<int> int_set;auto f = [&int_set]() { try { std::random_device rd; std::mt19937 gen(rd()); std::uniform_