并行和并发

并发编程是指在一台处理器上“同时”处理多个任务。

宏观并发:在一段时间内,有多个程序在同时运行。

微观并发:在同一时刻只能有一条指令执行,但多个程序指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个程序快速交替的执行。

并行 parallel同一时刻,多条指令在多个处理器上同时执行。

并发 concurrency:在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,通过cpu时间片轮转使多个进程快速交替的执行。

通俗来讲,并行是两组队列同时使用一个进程;并发是两个队列分别交替使用两个进程

进程并发

程序,以Go语言为例,是指编译好的二进制文件,在磁盘上,不占用系统资源(cpu、内存、打开的文件、设备、锁....)

进程,是一个抽象的概念,与操作系统原理联系紧密。以Go语言为例,将编译好的程序运行起来,在内存空间中形成一个独立的内存体,内存体有自己的独立空间,上级挂靠单位是操作系统。

进程是操作系统进行资源分配和调度的一个独立单位,一般由程序,数据集合和进程控制块三部分组成。

  • 程序:描述进程完成的功能,是控制进程执行的指令集;
  • 数据集合:程序在执行时所需要的数据和工作区;
  • 程序控制块PCB:Program Control Block,包含进程的描述信息和控制信息,是进程存在的唯一标志。

进程是活跃的程序,占用系统资源。在内存中执行。同一个程序也可以加载为不同的进程(彼此之间互不影响)

进程状态

进程基本的状态有5种。分别为初始态,就绪态,运行态,挂起态与终止态。其中初始态为进程准备阶段,常与就绪态结合来看。

线程的任务调度

大部分操作系统的任务调度是采用时间片轮转的抢占式调度方式。

时间片轮转是指,在一个进程中,当线程任务执行几毫秒后,由操作系统内核进行调度,通过硬件计数器终端处理器,让线程强行暂停,并将该线程的寄存器放入内存中,通过查看线程列表决定接下来执行哪一个线程,并从内存中恢复该线程的寄存器,最后恢复该线程的执行,从而去执行下一个任务。

时间片轮转中,任务执行那段时间叫做时间片,任务正在执行时的状态叫运行状态,被暂停的线程任务状态叫做就绪状态,意为等待下一个属于它的时间片的到来。

由于CPU的执行效率非常高,(i5 6600 约200亿/秒,奔腾4 约13亿/秒)CPU preformance 时间片非常短,在各个任务之间快速地切换,给人的感觉就是多个任务在“同时进行”,这也就是我们所说的并发。多任务运行过程的示意图如下:

进程实现并发时会出现的问题呢

孤儿进程: 父进程先于子进程结束,则子进程成为孤儿进程,子进程的父进程成为init进程,称为init进程领养孤儿进程。

僵尸进程: 进程终止,父进程尚未回收,子进程残留资源(PCB)存放于内核中,变成僵尸(Zombie)进程。

线程并发

在早期操作系统当中,没有线程的概念,进程是最小分配资源与执行单位,可以看做是一个进程中只有一个线程,故进程即线程。所以线程LWP被称为::Lightweight process,轻量级的进程,是程序执行中一个单一的顺序控制流程,在Linux操作系统下,线程的本质仍是进程。

线程有独立的PCB,但没有独立的地址空间,各个线程之间共享程序的内存空间。

进程和线程的区别

  • 进程:最小分配资源单位,可看成是只有一个线程的进程。
  • 线程:最小的执行单位
  • 一个进程由一个或多个线程组成
  • 进程之间相互独立,同一进程下的各个线程之间共享程序的内存空间

协程并发

协程 coroutines,是一种基于线程之上,但又比线程更加轻量级的存在,这种由程序来管理的轻量级线程叫做『用户空间线程』,具有对内核来说不可见的特性。

多数语言在语法层面并不直接支持协程,而是通过库的方式支持,但用库的方式支持的功能也并不完整,比如仅仅提供协程的创建、销毁与切换等能力。如果在这样的轻量级线程中调用一个同步 IO 操作,比如网络通信、本地文件读写,都会阻塞其他的并发执行轻量级线程,从而无法真正达到轻量级线程本身期望达到的目标。

协程和线程的区别

  • 占用资源:线程,初始单位为1MB,固定不可变;协程初始一般为 2KB,可随需要而增大。
  • 调度:线程,由操作系统内核完成,协程,由用户完成。
  • 性能: 线程,占用资源高,频繁创建销毁带来性能问题。占用资源小,不会带来严重的性能问题。
  • 数据: 线程,多线程需要锁机制确保数据一致性和可见性;而线程因为只有一个进程,不存在同时读/写冲突,协程中控制共享数据不用加锁,顾执行效率较线程高。

Go并发 goroutine

Go语言在语言级别支持协程,叫goroutine。Go语言标准库提供的所有系统调用操作(包括所有同步IO操作),都会出让CPU给其他goroutine。这种轻量级线程的切换管理不依赖于系统的线程和进程,也不需要依赖于CPU的核心数量。

Go语言为并发编程而内置的上层API基于顺序通信进程模型CSP(communicating sequential processes)。这就意味着显式锁都是可以避免的,因为Go通过相对安全的通道发送和接受数据以实现同步,这大大地简化了并发程序的编写。

Go语言中的并发程序主要使用两种手段来实现。goroutine和channel。

什么是goroutine

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

goroutine是Go并行设计的核心。goroutine说到底其实就是协程,它比线程更小,十几个goroutine可能体现在底层就是五六个线程,Go语言内部帮你实现了这些goroutine之间的内存共享。执行goroutine只需极少的栈内存(大概是4~5KB),当然会根据相应的数据伸缩。也正因为如此,可同时运行成千上万个并发任务。goroutine比thread更易用、更高效、更轻便。

MPG模型

M 操作系统的线程抽象,一个M直接关联了一个内核线程;代表着真正执行计算的资源。

P Processor,提供相关执行环境的上下文,处理用户级代码逻辑的处理器,P的数量由用户设置的GOMAXPROCS决定,但是不论GOMAXPROCS设置为多大,P的数量最大为256。

G Goroutine,G并非执行体,每个G需要绑定到P才能被调度执行。

在操作系统每一个线程都有一个固定大小的块来做栈,这个栈会用来存储当前正在被调用或挂起(指在调用其它函数时)的函数的内部变量。

在Go语言中,每一个goroutine是一个独立的执行单元,goroutine的栈采取了动态扩容方式, 初始时仅为2KB,随着任务执行按需增长,最大可达1GB(64最大1G,32位最大256M)

上图,图中P正在执行的Goroutine为蓝色的,处于待执行状态的Goroutine为灰色的,灰色的Goroutine形成了一个队列runqueues。

在这里,当一个P关联多个G时,就会处理G的执行顺序,就是并发,当一个P在执行一个协程工作时,其他的会在等待,当正在执行的协程遇到阻塞情况,例如IO操作等,go的处理器就会去执行其他的协程,因为对于类似IO的操作,处理器不知道你需要多久才能执行结束,所以他不回去等你执行完。

references

go语言并发编程

进程和线程

a

groutine之间的调度

golang:并发编程总结的更多相关文章

  1. golang并发编程

    golang并发编程 引子 golang提供了goroutine快速实现并发编程,在实际环境中,如果goroutine中的代码要消耗大量资源时(CPU.内存.带宽等),我们就需要对程序限速,以防止go ...

  2. Golang - 并发编程

    目录 Golang - 并发编程 1. 并行和并发 2. go语言并发优势 3. goroutine是什么 4. 创建goroutine 5. runtime包 6. channel是什么 7. ch ...

  3. golang并发编程goroutine+channel(一)

    go语言的设计初衷除了在不影响程序性能的情况下减少复杂度,另一个目的是在当今互联网大量运算下,如何让程序的并发性能和代码可读性达到极致.go语言的并发关键词 "go" go dos ...

  4. golang并发编程的两种限速方法

    引子 golang提供了goroutine快速实现并发编程,在实际环境中,如果goroutine中的代码要消耗大量资源时(CPU.内存.带宽等),我们就需要对程序限速,以防止goroutine将资源耗 ...

  5. Golang并发编程基础

    硬件 内存 作为并发编程一个基础硬件知识储备,首先要说的就是内存了,总的来说在绝大多数情况下把内存的并发增删改查模型搞清楚了其他的基本上也是异曲同工之妙. 内存芯片--即我们所知道的内存颗粒,是一堆M ...

  6. Golang并发编程优势与核心goroutine及注意细节

    Go语言为并发编程而内置的上层API基于CSP(communication sequential processes,顺序通信进程)模型.这就意味着显式锁都是可以避免的,比如资源竞争,比如多个进程同时 ...

  7. Golang并发编程进程通信channel了解及简单使用

    概念及作用 channel是一个数据类型,用于实现同步,用于两个协程之间交换数据.goroutine奉行通过通信来共享内存,而不是共享内存来通信.引用类型channel是CSP模式的具体实现,用于多个 ...

  8. Golang并发编程——goroutine、channel、sync

    并发与并行 并发和并行是有区别的,并发不等于并行. 并发 两个或多个事件在同一时间不同时间间隔发生.对应在Go中,就是指多个 goroutine 在单个CPU上的交替运行. 并行 两个或者多个事件在同 ...

  9. Golang并发编程中select简单了解

    select可以监听channel的数据流动select的用法与switch语法非常类似,由select开始的一个新的选择块,每个选择条件由case语句来描述 与switch语句可以选择任何使用相等比 ...

  10. Golang并发编程有缓冲通道和无缓冲通道(channel)

    无缓冲通道 是指在接收前没有能力保存任何值得通道.这种类型的通道要求发送goroutine和接收goroutine同时准备好,才能完成发送和接收操作.如果两个goroutine没有同时准备好,通道会导 ...

随机推荐

  1. 201871030134-余宝鹏 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告

    项目 内容 课程班级博客链接 班级博客 这个作业要求链接 作业要求 我的课程学习目标 1.体验软件项目开发中的两人合作,练习结对编程(Pair programming) 2.掌握GitHub协作开发程 ...

  2. 结对编程_stage1

    项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 结对项目-第一阶段 我在这个课程的目标是 从实践中学习软件工程相关知识(结构化分析和设计方法.敏捷开发方法. ...

  3. 二、python学习-函数

    类型判断 1.type()直接获取类型 2.isinstance 用法一:isinstance(值,类型) 返回真或假 用法二:isinstance(值,(类型1,类型2 ...)) 有一个类型满足 ...

  4. django-自定义用户登录(个人笔记)

    django自定义用户登录(个人笔记) 函数说明 1. render()函数:对用户请求做出响应 2. path()函数:定义路由 3. create()函数:增加数据表记录 配置settings.p ...

  5. electron项目踩坑--A JavaScript error occurred in the main process:document is not defined

    前言 记录electron-vue项目开发中遇到的一个错误,运行时报错如图: 控制台报错如下: ReferenceError: document is not defined at Object.&l ...

  6. C语言小知识(基于Linux)——个人笔记,不定时更新

    一.switch case语法,在case中定义变量时,需要在case的有效范围内使用花括号包起来,否则会编译报错: switch (name){ case "zhangSan": ...

  7. Day05_23_封装

    封装 什么是封装? 封装可以被认为是一个类的保护屏障,防止该类的代码和数据被外部类定义的代码随机访问.要访问该类的代码和数据,必须通过严格的接口控制.封装最主要的功能在于我们能修改自己的实现代 码,而 ...

  8. 这种ERP系统核查工作实际是在做无用功

    前段时间跟朋友聊起他们公司持续了好几年的ERP核查工作,此时他正在一家分公司做核查.ERP核查工作我是知道的,一个季度一次,每个模块出一个人去子公司巡回巡查,主要核查ERP系统的使用情况. 核查工作主 ...

  9. kube-router代替kube-proxy+calico

    使用kubeadm安装kubernetes,并使用kube-router代替kube-proxy+calico网络. 即:kube-router providing service proxy, fi ...

  10. Java并发-同步容器篇

    作者:汤圆 个人博客:javalover.cc 前言 官人们好啊,我是汤圆,今天给大家带来的是<Java并发-同步容器篇>,希望有所帮助,谢谢 文章如果有问题,欢迎大家批评指正,在此谢过啦 ...