进程、线程与协程的特点

进程、线程与协程的特点

Posted by A Chang on February 27, 2020

进程、线程与协程的特点

一句话概括

  1. 进程:程序的一次执行(有独立的内存空间)
  2. 线程:CPU的基本调度单位
  3. 协程:在用户程序中实现了协作式任务调度(由用户程序控制了任务调度)

三者的关系:进程里有线程,线程里有协程

讲讲协程

进程和线程的切换时由系统决定,而协程由我们程序员自己决定,比如Python中模块gevent下切换是遇到了耗时操作时才会切换
关于协程,你可能看的最多的就是这样一句话“协程就是用户态的线程”。
要理解是什么是“用户态的线程”,必然就要先理解什么是“内核态的线程”。 内核态的线程是由操作系统来进行调度的,在切换线程上下文时,要先保存上一个线程的上下文,然后执行下一个线程,当条件满足时,切换回上一个线程,并恢复上下文。协程也是如此,只不过,用户态的线程不是由操作系统来调度的,而是由程序员来调度的,是在用户态的。
yield这个关键字就是用来产生中断, 并保存当前的上下文的, 比如说程序的一段代码是访问远程服务器,那这个时候CPU就是空闲的,就用yield让出CPU,接着执行下一段的代码,如果下一段代码还是访问除CPU以外的其它资源,还可以调用yield让出CPU. 继续往下执行,这样就可以用同步的方式写异步的代码了。

进程与线程的使用场景

  • 多进程适合在CPU密集操作(cpu操作指令比较多,如位多的的浮点运算)
    CPU密集型: 大部分时间用来做计算,逻辑判断等CPU动作的程序称之CPU密集型
  • 多线程适合在IO密性型操作(读写数据操作比多的的,比如爬虫)
    IO密集型: 系统运行,大部分的状况是CPU在等 I/O(硬盘/内存)的读/写

有阻塞同时需要大量cpu计算时使用多线程比较好

PHP中进程与线程的使用场景?

PHP 实现的线程安全主要是使用线程安全资源管理器(Thread Safe Resource Manager 简称TSRM)机制对全局变量和静态变量进行了隔离,将全局变量和静态变量给每个线程都复制了一份,各线程使用的都是主线程的一个备份,从而避免了变量冲突,也就不会出现线程安全问题。
PHP对多线程的封装保证了线程安全,不用考虑对全局变量加各种锁来避免读写冲突了,同时也减少了出错的机会,写出的代码更加安全。
但因此也导致了,子线程一旦开始运行,主线程便无法再对子线程运行细节进行调整了,线程一定程度上失去了线程之间通过全局变量进行消息传递的能力。
同时PHP开启线程安全选项后,使用TSRM机制分配和使用变量时也会有额外的损耗,所以在不需要多线程的PHP环境中,使用PHP的ZTS(非线程安全)版本就好。

进程通信:

每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过操作系统内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信。

进程间通信方式有:

  1. 匿名管道通信
  2. 高级管道通信
  3. 命名管道通信
  4. 消息队列通信
  5. 信号量通信
  6. 信号
  7. 共享内存通信
  8. 套接字通信

总结

进程调度可以很好的控制资源分配,线程调度让进程内部不因某个操作阻塞而整体阻塞。协程则是在用户态来优化程序,让程序员以写同步代码的方式写出异步代码般的效率。