进程、线程、轻量级进程、协程和go中的Goroutine

一、进程

操作系统中最核心的概念是进程,分布式系统中最重要的问题是进程间通信。

进程是“程序执行的一个实例” ,担当分配系统资源的实体。进程创建必须分配一个完整的独立地址空间。

进程切换只发生在内核态,两步:1 切换页全局目录以安装一个新的地址空间 2 切换内核态堆栈和硬件上下文。  另一种说法类似:1 保存CPU环境(寄存器值、程序计数器、堆栈指针)2修改内存管理单元MMU的寄存器 3 转换后备缓冲器TLB中的地址转换缓存内容标记为无效。

二、线程

书中的定义:线程是进程的一个执行流,独立执行它自己的程序代码

维基百科:线程英语thread)是操作系统能够进行运算调度的最小单位。

线程上下文一般只包含CPU上下文及其他的线程管理信息。线程创建的开销主要取决于为线程堆栈的建立而分配内存的开销,这些开销并不大。线程上下文切换发生在两个线程需要同步的时候,比如进入共享数据段。切换只CPU寄存器值需要存储,并随后用将要切换到的线程的原先存储的值重新加载到CPU寄存器中去。

用户级线程主要缺点在于对引起阻塞的系统调用的调用会立即阻塞该线程所属的整个进程。内核实现线程则会导致线程上下文切换的开销跟进程一样大,所以折衷的方法是轻量级进程(Lightweight)。在linux中,一个线程组基本上就是实现了多线程应用的一组轻量级进程。我理解为 进程中存在用户线程、轻量级进程、内核线程。

语言层面实现轻量级进程的比较少,stackless python,erlang支持,java并不支持。

三、协程

协程的定义?颜开、许式伟均只说协程是轻量级的线程,一个进程可轻松创建数十万计的协程。仔细研究下,个人感觉这些都是忽悠人的说法。从维基百科上看,从Knuth老爷子的基本算法卷上看“子程序其实是协程的特例”。子程序是什么?子程序英语:Subroutine, procedure, function, routine, method, subprogram),就是函数嘛!所以协程也没什么了不起的,就是种更一般意义的程序组件,那你内存空间够大,创建多少个函数还不是随你么?

协程可以通过yield来调用其它协程。通过yield方式转移执行权的协程之间不是调用者与被调用者的关系,而是彼此对称、平等的。协程的起始处是第一个入口点,在协程里,返回点之后是接下来的入口点。子例程的生命期遵循后进先出(最后一个被调用的子例程最先返回);相反,协程的生命期完全由他们的使用的需要决定。

线程和协程的区别:

一旦创建完线程,你就无法决定他什么时候获得时间片,什么时候让出时间片了,你把它交给了内核。而协程编写者可以有一是可控的切换时机,二是很小的切换代价。从操作系统有没有调度权上看,协程就是因为不需要进行内核态的切换,所以会使用它,会有这么个东西。赖永浩和dccmx 这个定义我觉得相对准确  协程-用户态的轻量级的线程。(http://blog.dccmx.com/2011/04/coroutine-concept/)

为什么要用协程:

协程有助于实现:

  • 状态机:在一个子例程里实现状态机,这里状态由该过程当前的出口/入口点确定;这可以产生可读性更高的代码。
  • 角色模型:并行的角色模型,例如计算机游戏。每个角色有自己的过程(这又在逻辑上分离了代码),但他们自愿地向顺序执行各角色过程的中央调度器交出控制(这是合作式多任务的一种形式)。
  • 产生器:它有助于输入/输出和对数据结构的通用遍历。

颜开总结的支持协程的常见的语言和平台,可做参考,但应深入调研下才好。

四、go中的Goroutine

go中的Goroutine, 普遍认为是协程的go语言实现。《Go语言编程》中说goroutine是轻量级线程(即协程coroutine, 原书90页). 在第九章进阶话题中, 作者又一次提到, "从根本上来说, goroutine就是一种go语言版本的协程(coroutine)" (原书204页). 但作者Rob Pike并不这么说。

“一个Goroutine是一个与其他goroutines 并发运行在同一地址空间的Go函数或方法。一个运行的程序由一个或更多个goroutine组成。它与线程、协程、进程等不同。它是一个goroutine。”

在栈实现上,它的编译器分支下的实现gccgo是线程pthread,6g上是多路复用的threads(6g/8g/5g分别代表64位、32位及Arm架构编译器)

infoQ一篇文章介绍特性也说道: goroutine是Go语言运行库的功能,不是操作系统提供的功能,goroutine不是用线程实现的。具体可参见Go语言源码里的pkg/runtime/proc.c

老赵认为goroutine就是把类库功能放进了语言里。

goroutine的并发问题:goroutine在共享内存中运行,通信网络可能死锁,多线程问题的调试糟糕透顶等等。一个比较好的建议规则:不要通过共享内存通信,相反,通过通信共享内存。

并行 并发区别:

并行是指程序的运行状态,要有两个线程正在执行才能算是Parallelism;并发指程序的逻辑结构,Concurrency则只要有两个以上线程还在执行过程中即可。简单地说,Parallelism要在多核或者多处理器情况下才能做到,而Concurrency则不需要。(http://stackoverflow.com/questions/1050222/concurrency-vs-parallelism-what-is-the-difference)

时间: 2024-10-10 14:50:51

进程、线程、轻量级进程、协程和go中的Goroutine的相关文章

进程池与线程池、协程、协程实现TCP服务端并发、IO模型

进程池与线程池.协程.协程实现TCP服务端并发.IO模型 一.进程池与线程池 1.线程池 ''' 开进程开线程都需要消耗资源,只不过两者比较的情况下线程消耗的资源比较少 在计算机能够承受范围内最大限度的利用计算机 什么是池? 在保证计算机硬件安全的情况下最大限度的利用计算机 池其实是降低了程序的运行效率,但是保证了计算机硬件的安全 (硬件的发展跟不上软件的速度) ''' from concurrent.futures import ThreadPoolExecutor import time p

Python--线程队列(queue)、multiprocessing模块(进程对列Queue、管道(pipe)、进程池)、协程

队列(queue) 队列只在多线程里有意义,是一种线程安全的数据结构. get与put方法 ''' 创建一个"队列"对象 import queue q = queue.Queue(maxsize = 10) queue.Queue类即是一个队列的同步实现.队列长度可为无限或者有限.可通过Queue的构造函数的可选参数maxsize来设定队列长度.如果maxsize小于1就表示队列长度无限. 将一个值放入队列中: q.put() 调用队列对象的put()方法在队尾插入一个项目.put()

linux内核——进程,轻量级进程,线程,线程组

1.进程.轻量级进程.线程.线程组之间的关系 2.及它们的标识相关说明 一.进程.轻量级进程.线程.线程组之间的关系 借助上图说明: 进程P0有四条执行流,即线程, 主线程t0是它的第一个线程,且与进程P0相关联, 之后衍生出t1.t2.t3三个线程,这三个线程与轻量级进程P1.P2.P3一一关联, 所有的进程.轻量级进程.线程组成了线程组. 轻量级进程也是进程,只不过它与某进程的某特定线程相关联. 二.它们的标识相关说明 pid是进程标识符,tgid是线程组标识符 每个进程都有自己的pid,如

异步回调,事件,线程池与协程

在发起一个异步任务时,指定一个函数任务完成后调用函数 为什么需要异步 在使用线程池或进程池提交任务时想要任务的结果然后将结果处理,调用shudown 或者result会阻塞 影响效率,这样的话采用异步调用 比如result本来是用水壶烧水烧开了拿走,烧下一个 用shutdown可以将水壶一起烧但是一个一个拿走 call_done_back是一起烧,每个好了会叫你拿走做其他事 . 1.使用进程池时,回调函数都是主进程中执行执行 2. 使用线程池时,回调函数的执行线程是不确定的,哪个线程空闲就交给哪

异步调用,线程队列,时间,协程

异步的使用场景 爬虫: 1.从目标站点下载网页数据,本质是HTML格式字符串 2.用re从字符串中提取出你所需要的数据 #使用进程池 from concurrent.futures import ProcessPoolExecutor import requests,re,os def get_data(url): print('%s正在请求%s'%(os.getpid(),url)) response = requests.get(url) #获取网页数据包含报头 print('%s请求%s成

python 38 线程队列与协程

目录 1. 线程队列 1.1 先进先出(FIFO) 1.2 后进先出(LIFO)堆栈 1.3 优先级队列 2. 事件event 3. 协程 4. Greenlet 模块 5. Gevent模块 1. 线程队列 1.1 先进先出(FIFO) import queue q = queue.Queue(3) q.put('a') q.put('b') q.put('c') print(q.qsize()) # 队列大小 print(q.get()) print(q.get()) print(q.get

线程进阶之线程队列、线程池和协程

本节目录: 1.线程队列 2.线程池 3.协程 一.线程队列 线程之间的通信我们列表行不行呢,当然行,那么队列和列表有什么区别呢? queue队列 :使用import queue,用法与进程Queue一样 queue is especially useful in threaded programming when information must be exchanged safely between multiple threads. class queue.Queue(maxsize=0)

协程及Python中的协程

阅读目录 1 协程 2 Python中如何实现协程 回到顶部 1 协程 1.1协程的概念 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程.(其实并没有说明白~) 我觉得单说协程,比较抽象,如果对线程有一定了解的话,应该就比较好理解了. 那么这么来理解协程比较容易: 线程是系统级别的,它们是由操作系统调度:协程是程序级别的,由程序员根据需要自己调度.我们把一个线程中的一个个函数叫做子程序,那么子程序在执行过程中可以中断去执行别的子程序:别的子程

区分python进程、线程、携协程

进程: 概念:对各种资源管理的集合.(线程也是一种资源) 使用场景:CPU密集型运算,调用多进程,通过socket传输数据 线程: 概念:CPU运算的最小单元 使用场景:没有明确的切换条件,只能通过定时器切换 注:python中只允许单线程操作内存中数据,也就是说用python即使开了多个线程实际上也是切换执行,并没有利用CPU的多核性能.究其原因,是python的全局解释器锁(GIL).个人觉得,设计GIL与python的出发点相符,让程序更加简单,节省程序员时间,所以应用粗粒度的线程锁可以免