并行和并发

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

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

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

并行 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. Androi Studio 之 RelativeLayout

    RelativeLayout简介 •基本属性 •根据父容器定位 •父容器定位属性示意图 •根据兄弟组件定位 •根据兄弟组件定位 •margin(偏移) •padding(填充) •margin与pad ...

  2. 洛谷P1290欧几里德游戏

    题目地址 题目大意: 两个人st和ol博弈 有两个整数n,m 每次轮到一个人时候,需要选择用大的那个数减去小的那个数的倍数(不能减为负数) 最后得到0的为胜利者 思路: (以下讨论均在n<m的条 ...

  3. 2020 OO 第二单元总结

    只要跑得够快即使从头关到尾你也喜欢吗? 一.设计策略 1.1 总体策略概述 在多线程的协同和同步控制方面,我三次作业都是采用生产者/消费者模式(还憨憨地在内部分了customer.producer.t ...

  4. ASP.NET Core可视化日志组件使用

    前言 今天站长推荐一款日志可视化组件LogDashboard,可以不用安装第三方进程,只需要在项目中安装相应的Nuget包,添加数行代码,就可以实现拥有带Web页面的日志管理面板,十分nice哦. 下 ...

  5. Leedcode算法专题训练(排序)

    排序 快速排序 用于求解 Kth Element 问题,也就是第 K 个元素的问题. 可以使用快速排序的 partition() 进行实现.需要先打乱数组,否则最坏情况下时间复杂度为 O(N2). 堆 ...

  6. [C++]一篇文章搞懂C++中五花八门的各种初始化

    总结 初始化的概念:创建变量时赋予它一个值(不同于赋值的概念) 类的构造函数控制其对象的初始化过程,无论何时只要类的对象被创建就会执行构造函数 如果对象未被用户指定初始值,那么这些变量会被执行默认初始 ...

  7. Go+gRPC-Gateway(V2) 微服务实战,小程序登录鉴权服务(五):鉴权 gRPC-Interceptor 拦截器实战

    拦截器(gRPC-Interceptor)类似于 Gin 中间件(Middleware),让你在真正调用 RPC 服务前,进行身份认证.参数校验.限流等通用操作. 系列 云原生 API 网关,gRPC ...

  8. Bug Hunt UVA - 1596

      In this problem, we consider a simple programming language that has only declarations of onedimens ...

  9. vue 进阶学习(一): vue 框架说明和与其他框架的对比

    vue 框架说明和与其他框架的对比 一.说明 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层,不仅易于上手,还便于与第三 ...

  10. Spring Boot的自动配置原理及启动流程源码分析

    概述 Spring Boot 应用目前应该是 Java 中用得最多的框架了吧.其中 Spring Boot 最具特点之一就是自动配置,基于Spring Boot 的自动配置,我们可以很快集成某个模块, ...