Go学习笔记-协程和IO多路复用

简介: Go学习笔记-协程和IO多路复用

1、什么是协程?

  • 进程的虚拟地址空间划分为用户空间和内核空间
  • 线程是进程中的执行体,拥有一个执行入口,以及从虚拟地址空间中分配的栈(包括用户栈和内核栈)
  • 操作系统会记录线程控制信息,线程在获得时间片就可以被执行,CPU的指令指针和栈指针就会记录和执行线程相关的信息
  • 当线程创建了很多个执行体,并且也给这些执行体指定入口和分配栈内存,就可以按需调度这些执行体
  • 线程为了控制这些执行体的切换,也会记录这些执行体的信息,如ID、栈的位置、执行入口、执行现场等数据
  • 上述这种由线程创建的执行体就被称为协程,操作系统对协程一无所知,所以协程也可被称为用户态线程


2、协程间切换

  • 当用户线程获得CPU的时间片后,可以创建很多协程
  • 某个协程让出执行权时,会有协程栈保存执行现场等信息,接着就可以切换到其他协程
  • 协程获得执行权时,会根据之前协程栈保存的现场信息数据恢复执行
  • 协程是由用户态调度的多任务模型

3、协程和IO多路复用

  • 高并发成为为主流趋势,多进程模型请求下内存资源紧张
  • 多进程模型下,内核态和用户态切换两头忙
  • 协程这种用户态调度模型受到了关注
  • 协程和IO多路复用的结合成为很好的高并发解决方案

4、IO多路复用

  • 通过操作系统的进程控制信息可以找到进程打开文件描述信息、创建socket信息等
  • socket的操作都由操作系统来完成,需要用户程序通过系统调用来完成
  • 每创建一个socket,就会在打开的文件描述符表中创建一条记录信息,返回给用户程序的是socket描述符
  • 每个TCP socket被创建时,操作系统都会在内核空间分配度缓冲区、写缓冲区
  • 获取响应数据时,需要从读缓冲区拷贝数据
  • 要通过socket发送数据时,先要把数据拷贝到写缓冲区

  • 问题来了:
  • 当用户程序想要从读缓冲区获取数据,不一定有
  • 当用户程序想要发送数据的时候,写缓冲区,不一定有空间
  • 解决办法:
  • 阻塞式IO
  • 让出CPU进到等待队列里,等socket准备就绪,再次获得时间片时就可以继续执行了
  • 要处理一个socket,就需要占用一个线程,处理完才能继续下一个
  • 高并发场景下,开销很大
  • 非阻塞式IO
  • 不让出CPU,但需要一直询问socket是否准备就绪
  • 但这种忙等待的方式可能会空耗CPU,增加响应延迟
  • IO多路复用
  • 操作系统把需要等待的socket加入到监听集合
  • 用户程序就可以通过一次系统调用同时监听多个socket
  • Linux提供三种IO多路复用方式:
  • select
  • 可以设置要等待的描述符,也可以设置要等待的超时时间
  • 如果有准备好的fd,或到了超时时间,select系统函数就会返回
  • select系统函数支持可读、可写、可执行
  • fd_set是一个unsigned long数组,16个元素,每一位对应一个fd,最多可以监听1024个
  • 并且每次调用都需要传递所有监听的集合,需要频繁的从用户态到内核态拷贝数据
  • 每次都需要遍历整个监听集合判断可操作的fd

  • poll
  • 只能解决最大监听fd描述符的个数,其他问题依然没有得到解决

  • epoll
  • epoll提供三个关键接口
  • epoll_create用于创建epoll句柄
  • epoll_ctl用于添加或删除fd与对应的事件信息,可以指定要监听的fd和事件类型,可以传入额外的data数据,每次只需要传入一个fd,无需传入所有fd集合
  • epoll_wait返回fd集合都是已经准备就绪的,这样就不会阻塞和空耗CPU了
  • epoll有什么问题:
  • 比如当某个线程读fd时,可能读到一半时,CPU时间片就到了,需要让出执行权,保存现场数据
  • 需要等到下一次时间片的CPU执行权时,才能恢复现场继续执行
  • 解决办法:
  • 频繁切换线程,需要保存和恢复执行现场
  • 可以交给协程来处理,对于CPU来说同一个线程的多个协程无感知
  • 协程拥有自己的栈空间,用于保存和恢复现场相对比较容易,和具体的线程业务逻辑解耦了
相关文章
|
4月前
|
网络协议 安全 Linux
Linux C/C++之IO多路复用(select)
这篇文章主要介绍了TCP的三次握手和四次挥手过程,TCP与UDP的区别,以及如何使用select函数实现IO多路复用,包括服务器监听多个客户端连接和简单聊天室场景的应用示例。
114 0
|
4月前
|
存储 Linux C语言
Linux C/C++之IO多路复用(aio)
这篇文章介绍了Linux中IO多路复用技术epoll和异步IO技术aio的区别、执行过程、编程模型以及具体的编程实现方式。
164 1
Linux C/C++之IO多路复用(aio)
|
3月前
|
缓存 监控 前端开发
Go 语言中如何集成 WebSocket 与 Socket.IO,实现高效、灵活的实时通信
本文探讨了在 Go 语言中如何集成 WebSocket 与 Socket.IO,实现高效、灵活的实时通信。首先介绍了 WebSocket 和 Socket.IO 的基本概念及其优势,接着详细讲解了 Go 语言中 WebSocket 的实现方法,以及二者集成的重要意义和具体步骤。文章还讨论了集成过程中需要注意的问题,如协议兼容性、消息格式、并发处理等,并提供了实时聊天、数据监控和在线协作工具等应用案例,最后提出了性能优化策略,包括数据压缩、缓存策略和连接管理优化。旨在帮助开发者更好地理解并应用这些技术。
157 3
|
4月前
|
安全 Go 调度
探索Go语言的并发模式:协程与通道的协同作用
Go语言以其并发能力闻名于世,而协程(goroutine)和通道(channel)是实现并发的两大利器。本文将深入了解Go语言中协程的轻量级特性,探讨如何利用通道进行协程间的安全通信,并通过实际案例演示如何将这两者结合起来,构建高效且可靠的并发系统。
|
4月前
|
Linux C++
Linux C/C++之IO多路复用(poll,epoll)
这篇文章详细介绍了Linux下C/C++编程中IO多路复用的两种机制:poll和epoll,包括它们的比较、编程模型、函数原型以及如何使用这些机制实现服务器端和客户端之间的多个连接。
97 0
Linux C/C++之IO多路复用(poll,epoll)
|
4月前
|
Java Linux
【网络】高并发场景处理:线程池和IO多路复用
【网络】高并发场景处理:线程池和IO多路复用
111 2
|
4月前
|
监控 网络协议 Java
IO 多路复用? 什么是 IO 多路复用? 简单示例(日常生活)来解释 IO 多路复用 一看就懂! 大白话,可爱式(傻瓜式)教学! 保你懂!
本文通过日常生活中的简单示例解释了IO多路复用的概念,即一个线程通过监控多个socket来处理多个客户端请求,提高了效率,同时介绍了Linux系统中的select、poll和epoll三种IO多路复用的API。
244 2
Go语言的条件控制语句及循环语句的学习笔记
本文是Go语言的条件控制语句和循环语句的学习笔记,涵盖了if语句、if-else语句、if嵌套语句、switch语句、select语句以及for循环和相关循环控制语句的使用方法。
Go语言的条件控制语句及循环语句的学习笔记
|
5月前
|
网络协议 Java Linux
高并发编程必备知识IO多路复用技术select,poll讲解
高并发编程必备知识IO多路复用技术select,poll讲解
|
5月前
|
消息中间件 NoSQL Java
面试官:谈谈你对IO多路复用的理解?
面试官:谈谈你对IO多路复用的理解?
69 0
面试官:谈谈你对IO多路复用的理解?

热门文章

最新文章