golang 学习 (八)协程
一: 进程、线程 和 协程 之间概念的区别:
对于 进程、线程,都是有内核进行调度,有 CPU 时间片的概念,进行 抢占式调度(有多种调度算法)
(补充: 抢占式调度与非抢占(轮询任务调度)区别在于抢占式调度可以因为优先级高的任务抢占cpu,而轮询的不能)
对于 协程(用户级线程),这是对内核透明的,也就是系统并不知道有协程的存在,是完全由用户自己的程序进行调度的,因为是由用户程序自己控制,那么就很难像抢占式调度那样做到强制的 CPU 控制权切换到其他进程/线程,通常只能进行 协作式调度,需要协程自己主动把控制权转让出去之后,其他协程才能被执行到。
goroutine 和协程区别:
本质上,goroutine 就是协程。 不同的是,Golang 在 runtime、系统调用等多方面对 goroutine 调度进行了封装和处理,当遇到长时间执行或者进行系统调用时,会主动把当前 goroutine 的CPU (P) 转让出去,让其他 goroutine 能被调度并执行,也就是 Golang 从语言层面支持了协程。Golang 的一大特色就是从语言层面原生支持协程,在函数或者方法前面加 go关键字就可创建一个协程。
其他方面的比较
1. 内存消耗方面
每个 goroutine (协程) 默认占用内存远比 Java 、C 的线程少。
goroutine:2KB
线程:8MB
2. 线程和 goroutine 切换调度开销方面
线程/goroutine 切换开销方面,goroutine 远比线程小
线程:涉及模式切换(从用户态切换到内核态)、16个寄存器、PC、SP...等寄存器的刷新等。
goroutine:只有三个寄存器的值修改 - PC / SP / DX.
二: 进程、线程 和 协程 之间概念的区别:
线程是操作系统的内核对象,多线程编程时,如果线程数过多,就会导致频繁的上下文切换,这些 cpu 时间是一个额外的耗费。所以在一些高并发的网络服务器编程中,使用一个线程服务一个 socket 连接是很不明智的。于是操作系统提供了基于事件模式的异步编程模型。用少量的线程来服务大量的网络连接和I/O操作。但是采用异步和基于事件的编程模型,复杂化了程序代码的编写,非常容易出错。因为线程穿插,也提高排查错误的难度。
协程,是在应用层模拟的线程,他避免了上下文切换的额外耗费,兼顾了多线程的优点。简化了高并发程序的复杂度。
举个例子,一个高并发的网络服务器,每一个socket连接进来,服务器用一个协程来对他进行服务。代码非常清晰。而且兼顾了性能。
那么,协程是怎么实现的呢?
他和线程的原理是一样的,当 a线程 切换到 b线程 的时候,需要将 a线程 的相关执行进度压入栈,然后将 b线程 的执行进度出栈,进入 b线程 的执行序列。协程只不过是在 应用层 实现这一点。但是,协程并不是由操作系统调度的,而且应用程序也没有能力和权限执行 cpu 调度。怎么解决这个问题?
答案是,协程是基于线程的。内部实现上,维护了一组数据结构和 n 个线程,真正的执行还是线程,协程执行的代码被扔进一个待执行队列中,由这 n 个线程从队列中拉出来执行。这就解决了协程的执行问题。那么协程是怎么切换的呢?答案是:golang 对各种 io函数 进行了封装,这些封装的函数提供给应用程序使用,而其内部调用了操作系统的异步 io函数,当这些异步函数返回 busy 或 bloking 时,golang 利用这个时机将现有的执行序列压栈,让线程去拉另外一个协程的代码来执行,基本原理就是这样,利用并封装了操作系统的异步函数。包括 linux 的 epoll、select 和 windows 的 iocp、event 等。
由于golang是从编译器和语言基础库多个层面对协程做了实现,所以,golang的协程是目前各类有协程概念的语言中实现的最完整和成熟的。十万个协程同时运行也毫无压力。关键我们不会这么写代码。但是总体而言,程序员可以在编写 golang 代码的时候,可以更多的关注业务逻辑的实现,更少的在这些关键的基础构件上耗费太多精力。
但是由于协程是非抢占式的调度,无法实现公平的任务调用。
尽管,在任务调度上,协程是弱于线程的。但是在资源消耗上,协程则是极低的。一个线程的内存在 MB 级别,而协程只需要 KB 级别。而且线程的调度需要内核态与用户的频繁切入切出,资源消耗较高。
我们把协程的基本特点归纳为:
|
1
2
|
1. 协程调度机制无法实现公平调度2. 协程的资源开销是非常低的,一台普通的服务器就可以支持百万协程。 |
那么,近几年为何协程的概念可以大热。我认为一个特殊的场景使得协程能够广泛的发挥其优势,并且屏蔽掉了劣势 --> 网络编程。与一般的计算机程序相比,网络编程有其独有的特点。
|
1
2
3
|
1. 高并发(每秒钟上千数万的单机访问量)2. Request/Response。程序生命期端(毫秒,秒级)3. 高IO,低计算(连接数据库,请求API)。 |
golang 学习 (八)协程的更多相关文章
- swoole深入学习 8. 协程 转
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/yangyi2083334/article/ ...
- golang中最大协程数的限制(线程)
golang中最大协程数的限制 golang中有最大协程数的限制吗?如果有的话,是通过什么参数控制呢?还是通过每个协程占用的资源计算? 通过channel控制协程数的就忽略吧. 以我的理解,计算机资源 ...
- Python学习---线程/协程/进程学习 1220【all】
Python学习---线程基础学习 Python学习---线程锁/信号量/条件变量同步1221 Python学习---同步条件event/队列queue1223 Python学习---进程 1225 ...
- golang的多协程实践
go语言以优异的并发特性而闻名,刚好手上有个小项目比较适合. 项目背景: 公司播控平台的数据存储包括MySQL和ElasticSearch(ES)两个部分,编辑.运营的数据首先保存在MySQL中,为了 ...
- python学习笔记 协程
在学习异步IO模型前,先来了解协程 协程又叫做微线程,Coroutine 子程序或者成为函数,在所有语言中都是层级调用,比如a调用b,b调用c.c执行完毕返回,b执行完毕返回,最后a执行完毕返回 所以 ...
- Golang 入门 : goroutine(协程)
在操作系统中,执行体是个抽象的概念.与之对应的实体有进程.线程以及协程(coroutine).协程也叫轻量级的线程,与传统的进程和线程相比,协程的最大特点是 "轻"!可以轻松创建上 ...
- Golang的goroutine协程和channel通道
一:简介 因为并发程序要考虑很多的细节,以保证对共享变量的正确访问,使得并发编程在很多情况下变得很复杂.但是Go语言在开发并发时,是比较简洁的.它通过channel来传递数据.数据竞争这个问题在gol ...
- python学习之-- 协程
协程(coroutine)也叫:微线程,是一种用户态的轻量级线程,就是在单线程下实现并发的效果.优点:1:无需线程上下文切换的开销.(就是函数之间来回切换)2:无需原子操作锁定及同步的开销.(如改一个 ...
- Python学习之协程
8.8 协程 我们都知道线程间的任务切换是由操作系统来控制的,而协程的出现,就是为了减少操作系统的开销,由协程来自己控制任务的切换 协程本质上就是线程.既然能够切换任务,所以线程有两个最基本的 ...
- Python学习笔记--协程asyncio
协程的主要功能是单线程并发运行 假设有3个耗时不一样的任务.看看协程的效果. 先来看没有使用协程情况: #!/usr/bin/python3 # -*- coding:utf-8 -*- import ...
随机推荐
- codevs1504愚蠢的组合数 / RQNOJ愚蠢的组合数
1504 愚蠢的组合数 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 最近老师教了狗狗怎么算组合数,狗狗又 ...
- AtCoder Grand Contest 018题解
传送门 \(A\) 根据裴蜀定理显然要\(k|\gcd(a_1,...,a_n)\),顺便注意不能造出大于\(\max(a_1,...,a_n)\)的数 int n,g,k,x,mx; int mai ...
- [golang]7种 Go 程序性能分析方法
视频信息 Seven ways to Profile Go Applicationsby Dave Cheneyat Golang UK Conf. 2016 视频:https://www.youtu ...
- 《挑战30天C++入门极限》C++中利用构造函数与无名对象简化运算符重载函数
C++中利用构造函数与无名对象简化运算符重载函数 在完整描述思想之前,我们先看一下如下的例子,这个例子中的加运算符重载是以非成员函数的方式出现的: //程序作者:管宁 //站点:www.cn ...
- golang-flag - 命令行参数解析
flag - 命令行参数解析 在写命令行程序(工具.server)时,对命令参数进行解析是常见的需求.各种语言一般都会提供解析命令行参数的方法或库,以方便程序员使用.如果命令行参数纯粹自己写代码解析, ...
- macbook ios recovery and mount hfs+ journal and revert
sudo fsck.hfsplus -fryd /dev/sdc2 /sbin/fsck_hfs -yprd /dev/partitionName---can not fix b-tree node ...
- CentOS安装相应版本的内核源码
昨天接到同事给安排的新任务,测试系统性能:网上查了些资料,目测perf功能很强大,而且是内核源码自带的,编译安装即可使用:看了下自己的虚拟机,没有内核源码,好吧,装一个: 查看一下系统版本: #cat ...
- [XLua]热更新四部曲视频教程+示例源码
基于Unity2017 xLua是由腾讯维护的一个开源项目,xLua为Unity. .Net. Mono等C#环境增加Lua脚本编程的能力,借助xLua,这些Lua代码可以方便的和C#相互调用.自20 ...
- Java实现简单RPC框架(转)
一.RPC简介 RPC,全称Remote Procedure Call, 即远程过程调用,它是一个计算机通信协议.它允许像本地服务一样调用远程服务.它可以有不同的实现方式.如RMI(远程方法调用).H ...
- python统计apache、nginx访问日志IP访问次数并且排序(显示前20条)【转】
前言:python统计apache.nginx访问日志IP访问次数并且排序(显示前20条).其实用awk+sort等命令可以实现,用awk数组也可以实现,这里只是用python尝试下. apach ...