协程与线程的区别(swoole版解析)

注意,协程的客户端内执行其实是同步的,不要理解为异步,它只是遇到IO阻塞时能让出执行权,切换到其他协程而已,不能和异步混淆。

一 概念

  1. 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。
  2. 线程是指进程内的一个执行单元,也是进程内的可调度实体。线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。
  3. 协程是一种用户态的轻量级线程,协程的调度完全由用户控制。从技术的角度来说,“协程就是你可以暂停执行的函数”。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

二 协程与线程的区别

  1. 一个线程可以多个协程,一个进程也可以单独拥有多个协程。
  2. 协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态。
  3. 线程是抢占式,而协程是非抢占式的,所以需要用户自己释放使用权来切换到其他协程,因此同一时间其实只有一个协程拥有运行权,相当于单线程的能力。
  4. 协程并不是取代线程, 而且抽象于线程之上, 线程是被分割的CPU资源, 协程是组织好的代码流程, 协程需要线程来承载运行, 线程是协程的资源, 但协程不会直接使用线程, 协程直接利用的是执行器(Interceptor), 执行器可以关联任意线程或线程池, 可以使当前线程, UI线程, 或新建新程.。
  5. 线程是协程的资源。协程通过Interceptor来间接使用线程这个资源

三 PHP7.2协程改动

在 PHP-7.2 版本中底层会分配 8K 的 stack 来存储协程的变量,zval 的尺寸为 16字节,因此 8K 的 stack 最大可以保存 512 个变量。协程栈内存占用超过 8K 后 ZendVM 会自动扩容

PHP-7.1、PHP-7.0 默认会分配 256K 栈内存

 

四 SWOOLE中协程数量

max_coroutine设置当前工作进程最大协程数量。超过max_coroutine底层将无法创建新的协程,底层会抛出错误,并直接关闭连接。

在Server程序中实际最大可创建协程数量等于 worker_num * max_coroutine

$server->set(array(
'max_coroutine' => 3000,
))

默认值为3000

 

五 当前项目的数据库连接池的协程channel

 
  • 通道与PHPArray类似,仅占用内存,没有其他额外的资源申请,所有操作均为内存操作,无IO消耗
  • 底层使用PHP引用计数实现,无内存拷贝。即使是传递巨大字符串或数组也不会产生额外性能消耗
  • swoole中channel与go的区别是,增加了最大读取时间参数,当超过此事件未得到消费数据或者未能新增消费数据自动抛出异常
consumer_num 消费者数量,表示当前通道为空,有N个协程正在等待其他协程调用push方法生产数据
producer_num 生产者数量,表示当前通道已满,有N个协程正在等待其他协程调用pop方法消费数据
queue_num 通道中的元素数量

array(
"consumer_num" => 0,
"producer_num" => 1,
"queue_num" => 10
);

 

六 当协程是处理IO阻塞较多的场景

 
个人理解:只要碰到IO阻塞,就跳出go函数,IO阻塞完成后就跳回go函数里

协程并不是一定缩短代码的执行时间,我在测试的发现:
1.没有io阻塞时,多个go运行切换,执行顺序是和正常的串行代码一样,但是消费的时间却比正常时间要高。
2.有io阻塞时,时间也是比正常时间要高。

因此 我个人认为协程的使用要注重场景,然后得达到比较高的并发量了才应当使用它来开发业务
比如:云盘系统,大文件下载,1G的文件,我们可以把文件分成n份,n份文件对应n个协程去处理,那效率和时间自然没得说了
原文地址:https://www.cnblogs.com/bushuwei/p/14700263.html