首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >快速上手,协程剖析

快速上手,协程剖析

作者头像
一见
发布2018-08-10 17:17:43
发布2018-08-10 17:17:43
7230
举报
文章被收录于专栏:蓝天蓝天

coroutine.pdf

协程也叫微线程,英文名称为coroutine。一个进程可以有多个线程,一个线程可以有多个协程,这是协程和线程间的关系。不同的是,线程由系统调度,但协程需要自己调度,协程运行在用户态。

Linux内核为协程编程提供了支持,相关的函数声明在ucontext.h头文件中。也可以借助longjmp、setjmp、pthread_attr_setstackaddr等组合实现,但复杂很多,ucontext提供的函数已帮助做了很多工作。要实现协程的并发(线程内的,显然是假并发,实际还是串行的),要求主动调用swapcontext进行切换。

协程编程实际就是用户态调度函数的执行次数,让单个线程,看起来像是多线程。基于它可以实现伪同步,也就是将异步变成同步调用。

协程的原理非常简单,假设任务A划分成A1、A2、A3三个子任务,任务B划分成任务B1和B2两个子任务。利用协程,让A和B可以并行进行,比如完成A1后,立即执行B1,B1完成后执行A2,A2完成后执行B2,B2完成后执行A3。

为达到这个目的,在执行A1时,A1结束前需要调用swapcontext切换到B1。同理B1完成时,也需要调用swapcontext切换到A2。下面这个示例可以直接编译执行,通过它可以体会到协程的效果。

代码语言:javascript
复制
 		// 协程示例 
 		// 编译: g++ -g -o x x.cpp 	
 		#include  
 		#include  // 协程相关api所在头文件 
 		#include  
 		// 定义3个协程,类似于3个线程 
 		static void foo(); 	
 		static void woo(); 	
 		static void zoo(); 	
 		static ucontext_t ctx1; // 协程zoo的上下文,由makecontext调用构造 
 		static ucontext_t ctx2; // 协程woo的上下文,由makecontext调用构造 
 		static ucontext_t ctx3; // 协程foo的上下文,由swapcontext自动构造 
 		// stack为new/malloc出来的也可以的 
 		static char stack1[4096]; // 协程zoo的栈,得合适大小,否则一样会出现栈溢出 	
 		static char stack2[8192]; // 协程woo的栈,得合适大小,否则一样会出现栈溢出 	
 		int main() 	
 		{ 	
 		printf("main 1\n"); 	
 		    // 构造协程zoo的上下文 
 		getcontext(&ctx1); 	
 		ctx1.uc_stack.ss_sp = stack1; 	
 		ctx1.uc_stack.ss_size = sizeof(stack1); 	
 		ctx1.uc_link = &ctx3; // 在ctx1之后的上下文 
 		makecontext(&ctx1, zoo, 0); // 在运行完zoo之后,运行ctx3 
 		    // 构造协程woo的上下文 
 		getcontext(&ctx2);	 	
 		ctx2.uc_stack.ss_sp = stack2; 	
 		ctx2.uc_stack.ss_size = sizeof(stack2); 	
 		ctx2.uc_link = &ctx1; 	
 		makecontext(&ctx2, woo, 0); // 在运行完zoo之后,运行ctx1 
 		foo(); 	
 		printf("main 2\n"); 	
 		return 0; 	
 		} 	
 		// 可把foo当成一个线程,不过它是微线程 
 		void foo() 	
 		{ 	
 		printf("%s 1\n", __func__); 	
 		    // 切换到ctx2执行,也就是执行woo,当前的保存在ctx3 
 		swapcontext(&ctx3, &ctx2); 	
 		    // 当切回到ctx3时,会执行以下代码段 
 		printf("%s 2\n", __func__); 	
 		} 	
 		// 也可把woo当成一个线程,不过它是微线程 
 		void woo() 	
 		{ 	
 		printf("%s\n", __func__); 	
 		} 	
 		// 也可把zoo当成一个线程,不过它是微线程 
 		void zoo() 	
 		{ 	
 		printf("%s\n", __func__); 	
 		} 	

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2014/07/01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档