Go语言: 万物皆异步
来源:https://www.jianshu.com/p/62c0cd107da3
同步和异步、阻塞和非阻塞
首先要明确的是,同步(Synchronous)和异步(Asynchronous),阻塞(Blocking)和非阻塞(Non-Blocking)是两种完全不同的概念。前者指的是一种事件通知、处理机制,而后者则是程序控制流程的差异。
我们以A调用B为例来说明两者之间的区别:
阻塞
只有当B任务完成后,程序控制权才会返回给A, A得以继续执行。非阻塞
B马上返回,此时B并没有完成,但A可以继续执行,B任务并不影响
A的执行。同步
A需要通过某种方式主动查询B是否完成。在blocking模式中,它表现为等待B返回;在non-blocking模式中表现为通过Future对象询问B是否完成,如果完成则取出结果,未完成则等待(阻塞)。异步
A在启动B任务时就不管了,继续执行自己的任务,当B完成时,由操作系统主动通知A,告知B已经完成。A可以在适宜的时候取出B的执行结果。在这种模式下,A完全不会因为B的执行而影响自己。
异步是解决web应用高并发的唯一方案
“传统的”一线程对一请求的模型直接决定了单机并不能处理过多的并发请求,而且这种模型下会导致很大的线程资源浪费。这里面原因有二:一是每条线程占用要使用较多的内存,在JVM中每创建一个线程就要消耗2M多的heap,于是内存大小就变成线程数量的瓶颈;二是当线程数据超过CPU核心数时,频繁的线程切换会变成一笔可观的开销,而且当你的程序因为查询数据库、执行RPC调用阻塞当前线程时,这个线程是完全不能运行的,不仅白白占用了内存,还增加了Context Switch的次数。
异步并不能加快你对于单个请求的处理速度,但是它能最大化的消灭资源浪费,从而大大提高单机并发极限。
Go的世界中,万物皆异步
Go中只有协程,而协程本质上就是异步。
为什么这么说呢?首先我们知道,协程(routine)跟线程是多对一的关系,routine本身不会被调度执行,它只能依靠操作系统的线程来运行。一个线程可以执行多个routine, Go运行时调度器负责进行调度处理。routine只有三种情况需要让出执行权,分别是system call, 锁竞争和主动让出执行权力。
system call
当发生系统调用时,执行当前routine的线程会block这是没得商量的,但go运行时会从它维护的线程池中取出一条空闲线程继续执行其它routine, 这样就做到了即使你block了routine,也不会影响其它routine的执行。这里可以类比于Netty中的I/O线程,如果你代码block了,则会卡住其他任务的执行,否则你必须在自己的线程池中执行会产生block的代码。网络I/O
调用net包下的网络I/O操作是不会阻塞线程的。当发起网络I/O请求时,go运行时会通过操作系统提供的epoll机制注册I/O事件,不会挂起实际干活的线程,只会切换goroutine而已。竞争
无论是锁竞争还是读写channel而导致routine被挂起,其背后的线程都是不会有任何block的,在OS看来线程一直在正常运行,从而大大降低了线程上下文切换的开销。主动让出执行权
同上面的竞争,主动让出执行权时背后的线程同样不会block。
仔细想想看,这跟前面讲的异步不是几乎一样的逻辑吗?区别是,Go语言中是Go自己的调度器来通知routine等待的IO事件是否完成,而其它非协程语言则是OS来通知。
因此,Go中我们虽然在以同步的方式编写代码,但却与异步有着异曲同工之妙。
Go语言: 万物皆异步的更多相关文章
- 万物皆有始有终: Hawk5即日起停止升级迭代
		
从即日起,Hawk将停止升级工作,其版本号将停留在5. https://github.com/ferventdesert/Hawk Hawk已经开发和维护6年时间了,它曾经承载了开发者很多的期待.背后 ...
 - Javascript万物皆对象?
		
在javascript的世界里,有这么一句话,万物皆对象. 但是这个对象,应该怎么理解呢? exm........??,难道值类型也是对象?!! 当然,不是. 准确地讲是对于“引用类型”而言. 那,在 ...
 - 20190814 On Java8 第三章 万物皆对象
		
第三章 万物皆对象 对象创建 数据存储 有5个不同的地方可以存储数据: 寄存器 (Registers) 最快的存储区域,位于CPU内部 .无法直接控制. 栈内存(Stack) 存在于常规内存 RAM ...
 - C#实现一个万物皆可排序的队列
		
需求 产品中需要向不同的客户推送数据,原来的实现是每条数据产生后就立即向客户推送数据,走的的是HTTP协议.因为每条数据都比较小,而数据生成的频次也比较高,这就会频繁的建立HTTP连接,而且每次HTT ...
 - 万物皆可集成系列:低代码释放用友U8+深度价值(2)—数据拓展应用
		
在上一篇内容我们介绍了如何利用低代码开发套件实现低代码应用与U8+系统的对接集成,本次给大家带来的是如何将用友U8+系统中的数据进行价值扩展和实际应用. 我们以生产物料齐套分析为例来说明如何利用低代码 ...
 - javascript是脚本语言?javascript万物皆对象?
		
呵呵哒!带你见识下js面对对象的魅力 是的是的,退后,朕要开始装逼了- 这是什么鸟东西?是的是的,装逼开始,2016年度最佳JS编译器,ES6标准出来后,小伙伴们对新特性摩拳擦掌,奈何浏览器支持把我们 ...
 - 大话JS面向对象之开篇万物皆对象------(ATM取款机引发的深思)
		
一,总体概要 OO(面向对象)概念的提出是软件开发工程发展的一次革命,多年来我们借助它使得很多大型应用程序得以顺利实现.如果您还没有掌握并使用OO进行程序设计和开发,那么您无疑还停留在软件开发的石器时 ...
 - 万物皆对象的JavaScript
		
写在前面: 经过前段时间对于H5语言的学习,开始慢慢适应现在的生活节奏和代码语言.从一开始的毫无头绪到现在可以大概地写出部分的网站静态页面,用了两个周的时间.作为一个之前从未接触过计算机语言的初学者来 ...
 - Python赋值原理:Python无变量,万物皆对象
		
有几个和以前的常见语言,比如c语言不同 改变变量数据不覆盖原来的 name = '苍老师' print(id(name)) name = '志玲' print(id(name)) 运行结果 73955 ...
 
随机推荐
- 4.用IntelliJ IDEA 创建Maven Web
			
一.File→New→ Project 二.Maven→org.apache.maven.archetypes:maven-archetype-webapp→Next(记得打钩) 三.填入后Next→ ...
 - Python用户终端输入
			
#用户输入,操作 print("python 用户输入操作") # input(提示字符串),函数阻塞程序,并提醒用户输入字符串 instr = input("pleas ...
 - k8s 集群管理和微服务 适合做啥
			
k8s 集群管理和微服务 适合做啥 都知道k8s是集群 适合微服务 有很多教程 但你可以先了解他能干啥 traefix 是负载均衡工具 k8s 适合部署无状态依赖的微服务 可以按需求开启多个微服务 管 ...
 - nosql Redis命令操作详解
			
Redis命令操作详解 一.key pattern 查询相应的key (1)redis允许模糊查询key 有3个通配符 *.?.[] (2)randomkey:返回随机key (3)type key: ...
 - C/C++知识总结 五  复合数据类型 壹(数组、字符串与string、结构)
			
C/C++复合数据类型 壹(数组.结构) 数组 数组的意义.定义与创建 一.二维数组应用 字符数组与字符串处理函数 数组与指针---关系密切 数组的意义与定义创建 意义:反映数据间的特点(通过把同一类 ...
 - DevOps技能自查表
			
前篇提到了DevOps的工作岗位要求,但是没有来的及深入细节,本文根据个人10年多的经验,尽量详细地列举DevOps所需要用到的一些技术和相关参考网站. Linux基础 Linux系统的基本概念: 必 ...
 - stm32:简单按键输入实现
			
开发环境keil4,芯片STM32F103C8T6 1.main.c //串口实验 #include "sys.h" #include "delay.h" #i ...
 - [转发]对ThreadPoolExecutor初识
			
知识点提前预知: Java.util.concurrent.ThreadPoolExecutor类是ExecutorSerivce接口的具体实现.ThreadPoolExecutor使用线程池中的一个 ...
 - MYSQL索引类型。MYSQLc储存引擎
			
MYSQL索引类型,MYSQLc储存引擎 MySQL索引创建与删除 MySQL存储引擎的 ...
 - mpvue小程序开发
			
查阅资料,看官方文档,知道mpvue是一个使用 Vue.js 开发小程序的前端框架(美团的开源项目).框架基于 Vue.js 核心,mpvue 修改了 Vue.js 的 runtime 和 compi ...