php协程和goroutine,浅谈协程和Go语言的Goroutine

0x00.前言

前面写了一篇

今天来学习Go语言的Goroutine机制,这也可能是Go语言最为吸引人的特性了,理解它对于掌握Go语言大有裨益,话不多说开始吧!

通过本文你将了解到以下内容:什么是协程以及横向对比优势

Go语言的Goroutine机制底层原理和特点

0x01.聊聊协程

大家对于进程、线程二位明星都很熟悉,但协程就没有火了,是协程不是携程哦!

协程并不是Go语言特有的机制,相反像Lua、Ruby、Python、Kotlin、C/C++等也都有协程的支持,区别在于有的是从语言层面支持、有的通过插件类库支持。Go语言是原生语言层面支持,本文也是从Go角度去理解协程。

6ab916bc19a0a350bb9110676a2d43a9.png

1.1 协程基本概念和提出者

协程英文是Coroutine译为协同程序,我们来看下维基百科对Coroutine的介绍:Coroutines are computer program components that generalize subroutines for non-preemptive multitasking, by allowing execution to be suspended and resumed.

Coroutines are well-suited for implementing familiar program components such as cooperative tasks, exceptions, event loops, iterators, infinite lists and pipes.

According to Donald Knuth, Melvin Conway coined the term coroutine in 1958 when he applied it to construction of an assembly program.The first published explanation of the coroutine appeared later, in 1963.

简单翻译一下:协同程序是一种计算机程序组件,它允许暂停和恢复执行,从而可以作为通用化的非抢占式多任务处理子程序。

协同程序非常适合实现例如协作任务、异常、事件循环、迭代器、管道等熟悉的程序组件。

根据唐纳德·克努特的说法,梅尔文·康威在1958年将Coroutine这个术语应用于装配程序的构建,直到在1963年才首次发表了阐述Coroutine的论文。

协程的提出者梅尔文·爱德华·康威是一位计算机科学家,除了协程之外他还创造了Conway's Law康威定律,他基于社会学观察提出了系统设计的一些观点,本文就不展开了,感兴趣的可以看下作者的论文How Do Committees Invent?:

1.2 协程和进线程的对比

我们来复习一下进线程和协程的一些基本特点吧:进程是系统资源分配的最小单位, 进程包括文本段text region、数据段data region和堆栈段stack region等。进程的创建和销毁都是系统资源级别的,因此是一种比较昂贵的操作,进程是抢占式调度其有三个状态:等待态、就绪态、运行态。进程之间是相互隔离的,它们各自拥有自己的系统资源, 更加安全但是也存在进程间通信不便的问题。

进程是线程的载体容器,多个线程除了共享进程的资源还拥有自己的一少部分独立的资源,因此相比进程而言更加轻量,进程内的多个线程间的通信比进程容易,但是也同样带来了同步和互斥的问题和线程安全问题,尽管如此多线程编程仍然是当前服务端编程的主流,线程也是CPU调度的最小单位,多线程运行时就存在线程切换问题,其状态转移如图:

468a8bf0869a435cd6e2fb32d6128851.png协程在有的资料中称为微线程或者用户态轻量级线程,协程调度不需要内核参与而是完全由用户态程序来决定,因此协程对于系统而言是无感知的。协程由用户态控制就不存在抢占式调度那样强制的CPU控制权切换到其他进线程,多个协程进行协作式调度,协程自己主动把控制权转让出去之后,其他协程才能被执行到,这样就避免了系统切换开销提高了CPU的使用效率。

抢占式调度和协作式调度的简单对比:

49bc32429d5b84d708a76e18de6275fa.png

看到这里我们不免去想:看着协作式调度优点更多,那么为什么一直是抢占式调度占上风呢?让我们继续一起学习,可能就能解答这个问题了。

1.3 实际工作中的我们

我们写程序的时经常需要考虑的因素就是提高机器使用率,这个非常好理解。当然机器使用率和开发效率维护成本往往存在权衡,说句大白话就是:要么费人力要么费机器,选一个吧!

机器成本里面最贵的就是CPU了,程序一般分为CPU密集型和IO密集型,对于CPU密集型我们的优化空间可能没那么多,但对于IO密集型却有非常大的优化空间,试想我们的程序总是处于IO等待中让CPU呼呼睡大觉,那该多糟糕。

为了提高IO密集型程序的CPU使用率,我们尝试多进程/多线程编程等让多个任务一起跑分时复用抢占式调度,这样提高了CPU的利用率,但由于多个进线程存在调度切换,这也有一定的资源消耗,因此进线程数量不可能无限增大。

我们现在写的程序大部分都是同步IO的,效率还不够高,因此出现了一些异步IO框架,但是异步框架的编程难度比同步框架要大,但不可否认异步是一个很好的优化方向,先不要晕,来看下同步IO和异步IO就知道了:同步是指应用程序发起I/O请求后需要等待或者轮询内核I/O操作完成后才能继续执行,异步是指应用程序发起I/O请求后仍继续执行,当内核I/O操作完成后会通知应用程序或者调用应用程序注册的回调函数。

我们以C/C++开发的服务端程序为例,Linux的异步IO出现的比较晚,因此像epoll之类的IO复用技术仍然有相当大的地盘,但是同步IO的效率毕竟不如异步IO,因此当前的优化方向包括:异步IO框架(像boost.asio框架)和协程方案(腾讯libco)。

d23eadc1e84e423a2c8cd5a6623281f6.png

0x02.Go和协程

我们知道协程是Coroutine,Go语言在语言层面对协程进行了原生支持并且称之为Goroutine,这也是Go语言强大并发能力的重要支撑,Go的CSP并发模型是通过Goroutine和channel来实现的,后续会专门写一下CSP并发模型。

2.1 协作式调度和调度器

协作式调度中用户态协程会主动让出CPU控制权来让其他协程使用,确实提高了CPU的使用率,但是不由得去思考用户态协程不够智能怎么办?不知道何时让出控制权也不知道何时恢复执行。

读到这里忽然明白了抢占式调度的优势了,在抢占式调度中都是由系统内核来完成的,用户态不需要参与,并且内核参与使得平台移植好,说到底还是各有千秋啊!

为了解决这个问题我们需要一个中间层来调度这些协程,这样才能让用户态的成千上万个协程稳定有序地跑起来,我们姑且把这个中间层称为用户态协程调度器吧!

2.2 Goroutine和Go的调度器模型

Go语言从2007年底开发直到今天已经发展了12年,Go的调度器也不是一蹴而就的,在最初的几个版本中Go的调度器也非常简陋,无法支撑大并发。

经过多个版本的迭代和优化,目前已经有很优异的性能了,不过我们还是来回顾一下Go调度器的发展历程(详见参考一):

b511ba7be17508d25bbd20336d607e54.png

图片来自网络

Go的调度器非常复杂,篇幅所限本文只提一些基本的概念和原理,后续会深入去展开Go的调度器。

最近几个版本的Go调度器采用GPM模型,其中有几个概念先看下:

d2dab8be024fd634b3e9fd4c0cd64399.png

图片来自网络

GPM模型使用一种M:N的调度器来调度任意数量的协程运行于任意数量的系统线程中,从而保证了上下文切换的速度并且利用多核,但是增加了调度器的复杂度。

来看两张图来进一步理解一下:

b0e18af7e71feba203c462fa06a6454f.png

图片来自网络

67ecfd96750dea59613afd43f4bd661d.png

整个GPM调度的简单过程如下:新创建的Goroutine会先存放在Global全局队列中,等待Go调度器进行调度,随后Goroutine被分配给其中的一个逻辑处理器P,并放到这个逻辑处理器对应的Local本地运行队列中,最终等待被逻辑处理器P执行即可。

在M与P绑定后,M会不断从P的Local队列中无锁地取出G,并切换到G的堆栈执行,当P的Local队列中没有G时,再从Global队列中获取一个G,当Global队列中也没有待运行的G时,则尝试从其它的P窃取部分G来执行相当于P之间的负载均衡。

Goroutine在整个生存期也存在不同的状态切换,主要的有以下几种状态:

058197024717d2e7ea864e81db673d09.png

画个状态图看下:

2513c1196ba1d2981211794b2d43f025.png

0x03.巨人的肩膀

0x04.往期精彩

0x05.关于我

有疑问加站长微信联系(非本文作者)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/443559.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java实现:月,日,年,周,访问量统计

一:工程截图: 二:运行效果图: 三:CountObjectInfo.java: package cn.csrc.base.count;import java.util.Date;public class CountObjectInfo {// 总访问量合计protected int totalCount 0;// 日访问量protected int d…

JavaMelody开源系统性能监控软件:

一:从网上搜索,发现 javamelody 监控web应用程序不错。 JavaMelody能够在QA和实际运行生产环境监测Java或Java EE应用程序服务器。并以图表的形式显示:Java内存和Java CPU使用情况,用户Session数量,JDBC连接数&#x…

java zoneoffset,java - 如何在java8中获取默认的ZoneOffset? - SO中文参考 - www.soinside.com...

tl;drOffsetDateTime.now().getOffset()但您可能应该使用时区而不是仅仅偏离UTC。ZoneId.systemDefault()Offset versus Time Zoneoffset-from-UTC只是一小时,几分钟和几秒钟 - 仅此而已。time zone是特定地区人民使用的偏移的过去,现在和未来变化的历史…

php声波模拟开门,关于 php使用扩展控制树莓派io 驱动超声波测距

经过昨天一下午&#xff0c;终于写好了基于只需要安装完毕&#xff0c;就可以调用函数了&#xff1a;<?php /*** Created by PhpStorm.* User: tioncico* Date: 19-7-6* Time: 下午4:45*/define(PI_TRIG,0);define(PI_ECHO,1);if (wiringPiSetup()false){echo "初始化…

Java和poi导出excel报表

一&#xff1a;poi jar下载地址&#xff1a;点击打开链接&#xff1a; 二&#xff1a;工程截图&#xff1a; 三&#xff1a;运行效果截图&#xff1a; 四&#xff1a;源代码&#xff1a; Student.java: package com.poi.bean;import java.util.Date;public class Student {pri…

sh.k7p.work/index.php,Laowang's Blogs

OpenDayLight(硼Boron版本)实战开发入门OpenDayLight[1](简写为ODL)的硼Boron(0.5.0)版本于2016-09-16 这几天刚刚发布。作为一款开源SDN网络控制器&#xff0c;依托于强大的社区支持以及丰富的功能特性&#xff0c;ODL成为了目前主流的SDN网络控制器开发平台。不仅为开发者提供…

Java和iText导出pdf文档

一&#xff1a;工程截图&#xff1a; 二&#xff1a;项目运行截图&#xff1a; 三&#xff1a;源代码&#xff1a; Book.java package com.iText.bean;public class Book {private int bookId;// 图书编号private String name;// 图书名称private String author;// 图书作者pr…

linux多进程原理,Linux进程调度

极简模式假设我的系统只有一种调度算法cfs那么有个调度的队列 cfs_rq所有running的进程都会 进入这个队列&#xff0c;不在running 或者其他情况会出队列&#xff0c;ok。则假设队列控制的算法有以下。cfs_rq_enqueuecfs_rq_dequeuecfs_rq_pick所操作的是进程描述符 task_struc…

openwrt使用linux内核版本,降低OpenWRT的Linux内核版本

不久前&#xff0c;为了移植某驱动程序&#xff0c;笔者可谓绞尽脑汁&#xff0c;在4.1内核版本上&#xff0c;尝试了很多次都没能成功&#xff0c;后来仔细分析&#xff0c;才知道是内核版本过高导致的&#xff0c;本文给出降低内核版本的方法&#xff0c;具体编译环境的搭建&…

linux天气软件,类似智能手机!Linux中安装Conky天气插件

如今&#xff0c;智能手机中很多都安装相匹配外观的天气小插件&#xff0c;而对于喜欢操作系统平台的用户而言&#xff0c;可以在你的Linux桌面中拥有像智能手机一样的天气外观。通过Flair Weather Conky可以将使用一个GUI工具Conky Manager在Linux中轻松地管理Conky。这里介绍…

linux安装下载中文包,linux下安装中文包和字体

在虚拟机中使用中文输入法和中文显示使用的是rhel5的镜像我把其镜像挂载在/mnt/cdrom中&#xff0c;然后切换到/Server目录下&#xff0c;安装支持中文字体Mount /dev/cdrom /mnt/cdromCd /mnt/cdrom/serverrpm -ivh fonts-chinese-3.02-9.6.el5.noarch.rpmrpm -ivh fonts-ISO8…

linux无桌面重做系统,Linux不需要重做系统

感谢hsyyf的投递但从系统构架上来讲&#xff0c;总所周知&#xff0c;Linux的稳定性远大于windows&#xff0c;单纯的使用不会引起系统的损坏。当不进行危险操作时&#xff0c;例如执行sudo rm-rf/*之类的命令&#xff0c;或者混用分区工具&#xff0c;是不会引起各种彻底性损坏…

linux远程连接工具putty使用方法,linux远程登陆工具putty使用

#putty工具百度下载即可&#xff0c;最好从官网下。安装时&#xff0c;除安装位置外&#xff0c;其余默认即可。1、使用命令ifconfig命令&#xff0c;记下eth0的IP&#xff0c;我的是192.168.1.1692、打开putty&#xff0c;并将查到的ip写在图中位置&#xff0c;下侧的Saved Se…

linux mint安装步骤,Linux mint 安装步骤

##Linux mint 安装步骤##家里的笔记本以前一直用Deepin系统&#xff0c;但是Deepin系统的wifi实在是太慢了。还有就是启动软件是有时候总没响应&#xff0c;卡死机。 最近重装系统&#xff0c;选择了mint ,在这里记录下安装步骤。###1.制作U盘启动盘###下载iso文件&#xff0c;…

linux 商业游戏,Ubuntu下安装试玩原生Linux版商业游戏Braid

这款原生Linux版商业游戏Braid国外出售价大约在80美元左右。每年在Linux平台上发布的原生商业游戏是屈指可数&#xff0c;而且这些游戏的质量也是参差不齐。不过这款原生Linux版商业游戏Braid还是值得一玩的&#xff0c;这款Braid游戏创意十足&#xff0c;您可以通过拼图和时间…

linux centos 7 crontab 启动,CentOS 7 Linux执行crontab 计划任务实操 - 好应网

[inlosc_lg_title]一、环境准备[/inlosc_lg_title]yum install vixie-cron #安装定时任务插件yum install crontabs #安装定时任务crontabs/bin/systemctl restart crond.service #启动服务/bin/systemctl reload crond.service #重新载入配置/bin/systemctl status crond.serv…

三羊献瑞c语言编程入门,蓝桥杯-三羊献瑞,

蓝桥杯-三羊献瑞&#xff0c;更多精彩文章请关注公众号『大海的BLOG』问题观察下面的加法算式&#xff1a;祥 瑞 生 辉 三 羊 献 瑞----------------三 羊 生 瑞 气其中&#xff0c;相同的汉字代表相同的数字&#xff0c;不同的汉字代表不同的数字&#xff0c;‘三’和‘祥’不…

倒果汁c语言,水果榨汁补维生素C?这些补维生素的错误别再犯了

原标题&#xff1a;水果榨汁补维生素C&#xff1f;这些补维生素的错误别再犯了蔬菜和水果作为维生素C、矿物质和植物纤维的重要来源&#xff0c;是每天餐桌上都要出现的食物&#xff0c;一旦水果蔬菜吃不够&#xff0c;身体就会开始找你麻烦。在处理蔬菜水果的时候&#xff0c;…

android 判断对象,Android网络判断知识小结

Android中判断当前网络是否可用应用场景&#xff1a;实现判断当前网络是否可用当前有可用网络&#xff0c;如下图&#xff1a;当前没有可用网络&#xff0c;如下图&#xff1a;实现步骤&#xff1a;1、获取ConnectivityManager对象Context context activity.getApplicationCon…

html选择器是什么,CSS3选择器是什么?

首先我们来看一下displaynone的意思是什么&#xff1f;display:none的意思&#xff1a;隐藏元素并脱离文档&#xff0c;流就是隐藏该区域&#xff0c;不占实际空间&#xff0c;但对后台来说真实存在&#xff0c;可以获取被隐藏的元素简单的来说就是将元素设置为none的时候既不会…