纤程/协程详细总结

看了一大堆讲协程的文章,都是看的似懂非懂,自己学习后就写一个总结了

微内核/宏内核

进程,线程,纤程/协程定义

进程资源分配最小单位,线程CPU调度/执行最小单位。
当运行一个程序,点击一次则启动一个进程放入内存执行,进程内UI,socket等功能并行运行。
这时候线程并行运行这些功能,线程不会额外分配内存空间,线程都共享所处进程内存空间

PC寄存器记录线程内数据执行到哪,CPU通过PC寄存器取数据计算,循环反复。
JVM内调用OS启动分配线程内存消耗1mb左右,开销巨大。所以为了减小线程上下文切换巨大开销,协程出现了。
JAVA的JMM中,每个线程都有自己的线程栈,协程模拟记录了PC stack/线程栈信息,不经过操作系统。
一个线程包含多个协程,JAVA不支持协程目前

以前负载均衡中间件文章写Nginx,lua那也提过协程

类似多线程,不是操作系统线程,所以创建切换开销比线程小
协程栈在用户进程空间模拟的,所以创建切换开销小
多线程是并发执行,一个瞬间多个流执行。协程强调协作,一瞬间能有一个运行
因为一瞬间只能一个运行,对临界区不用加锁,多线程则需要加
因为多线程有多个控制流,程序行为不可控,协程可控

优点:	
	1. 协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级  
   	2. 单线程内就可以实现并发的效果,最大限度地利用cpu
   	3. 程序行为可控
缺点:
 	1. 协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
 	2. 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程

Nginx每个worker进程都在epoll/kqueue上封装成协程,每个请求一个协程处理,与lua内建协程模型一致。
所以ngx_lua执行lua对c开销很小,高并发能力仍然很好

应用

	C语言常采用回调的方法:当异步完成时,回调脚本的一个已知的函数。如果程序执行到异步点时,跳回,当异步完成后,再回到跳回点继续执行。
	协程主要可以用于回调,协程是把异步过程,当作同步处理。

	比如JAVA中callable和future实现异步,JAVA仍然需要新建一个线程主动寻找结果
	Guava添加了监听器不需要主动寻找结果等,都不是很好。因为0x80中断/sysenter原语,
	用户态向内核态发送80中断,比如申请read函数,总要有很大内核上下文切换开销
		1 用户态发出80中断
		2 切换内核态
		3 中断向量表中查找read函数
		4 保存硬件现场,CS IP等寄存器值
		5 保存用户态程序堆栈和寄存器值
		6 执行中断例程,system call
			根据参数和找到的read函数,执行并返回
		7 恢复硬件现场
		8 返回用户态
		9 程序继续执行

	read的IO时间过长,多线程下会放弃CPU执行权,交于其他线程执行,会通过OS切换额外开销。
	单线程内开启协程,一旦遇到io,就会从应用程序级别(而非操作系统)控制切换,以此来提升效率(非io操作的切换与效率无关。
	所以如果使用协程,免去上下文切换,性能能大幅度提升

你可能感兴趣的:(纤程/协程详细总结)