【Go】通道:缓冲通道和非缓冲通道
目录
通道的基本概念
缓冲通道
非缓冲通道
总结
通道的基本概念
在Go语言中,通道是一种特殊的类型,用于在goroutine之间传递数据。你可以将通道想象为数据的传输管道。通道分为两种类型:
- 非缓冲通道(Unbuffered Channels):发送操作会阻塞,直到另一goroutine在对应的通道上执行接收操作,这时候数据才会被发送成功,发送goroutine才能继续执行。
- 缓冲通道(Buffered Channels):可以存储一定数量的值,无需立即有goroutine接收这些值。
缓冲通道
缓冲通道通过在make函数中指定第二个参数来创建,这个参数定义了通道可以存储的值的数量。在你提供的代码中,messages是一个缓冲通道,其容量为2:
messages := make(chan string, 2)
这意味着即使没有goroutine准备好接收数据,你也可以往messages通道发送两个字符串。如果尝试发送更多的数据,那么发送操作会阻塞,直到有空间可用。
messages <- "buffered"
messages <- "channel"fmt.Println(<-messages)
fmt.Println(<-messages)
简单代码:
package mainimport "fmt"func main() {// Here we `make` a channel of strings buffering up to// 2 values.messages := make(chan string, 2)// Because this channel is buffered, we can send these// values into the channel without a corresponding// concurrent receive.messages <- "buffered"messages <- "channel"// Later we can receive these two values as usual.fmt.Println(<-messages)fmt.Println(<-messages)
}
使用场景
缓冲通道在需要解耦发送者和接收者的速率时非常有用。例如,在一个情况下,可能生产者生成数据的速度快于消费者处理数据的速度,那么一个适当大小的缓冲可以帮助平衡这种速率差异,减少直接阻塞的发生。
这里将展示一个使用缓冲通道的Go程序,该程序模拟一个简单的并行任务处理场景,其中多个工人(goroutine)并发地从一个任务队列(缓冲通道)中获取任务并执行。此示例中,我们将创建一个任务通道和一个结果通道,每个工人都从任务通道接收任务,处理完毕后将结果发送到结果通道。这种方式非常适用于需要任务分发和结果收集的场景。
package mainimport ("fmt""time""sync"
)// Task 表示一个简单的任务,这里仅仅是一个数值
type Task int// Result 表示任务处理的结果,这里包含任务原始值和处理后的信息
type Result struct {Task TaskInfo string
}func worker(id int, tasks <-chan Task, results chan<- Result, wg *sync.WaitGroup) {defer wg.Done()for task := range tasks {fmt.Printf("工人 %d 开始处理任务 %d\n", id, task)// 模拟任务处理时间time.Sleep(time.Second)// 发送结果到结果通道results <- Result{Task: task, Info: fmt.Sprintf("工人 %d 完成", id)}}
}func main() {// 创建缓冲通道tasks := make(chan Task, 10)results := make(chan Result, 10)// 使用 WaitGroup 来等待所有工人完成var wg sync.WaitGroup// 启动三个工人 goroutinesfor i := 1; i <= 3; i++ {wg.Add(1)go worker(i, tasks, results, &wg)}// 分发任务for j := 1; j <= 5; j++ {tasks <- Task(j)}// 关闭任务通道,表示不再有任务被发送close(tasks)// 等待所有工人完成wg.Wait()// 关闭结果通道close(results)// 输出所有处理结果for result := range results {fmt.Printf("任务 %d: %s\n", result.Task, result.Info)}
}
程序说明
- 任务和结果结构:我们定义了两种类型,
Task和Result,分别代表任务和处理结果。 - 工人goroutine:
worker函数是每个工人的行为定义。它持续从任务通道接收任务,处理它们(这里仅模拟为等待1秒),然后将结果发送到结果通道。 - 主函数中的并发执行:
- 创建并初始化缓冲通道
tasks和results。 - 启动3个工人goroutine,每个都在独立的线程中执行。
- 发送5个任务到任务通道。
- 关闭任务通道,告知工人不再有新任务。
- 使用
sync.WaitGroup来等待所有工人的任务处理完成。 - 关闭结果通道并打印所有结果。
- 创建并初始化缓冲通道
这个例子展示了如何使用缓冲通道来管理并发任务的分配和结果收集,使得多个工人能够并行处理任务,同时主程序能够等待所有任务完成并最终收集所有的处理结果。这种模式在实际开发中非常有用,尤其是在需要并行处理大量数据或任务的应用场景中。继续努力,不断深化对Go并发编程的理解和应用!
非缓冲通道
Go语言中的非缓冲通道是一种在goroutine之间进行通信的机制,它在发送和接收数据时具有同步的特性。在非缓冲通道上,数据的发送必须有对应的接收操作同时准备好,否则发送操作会阻塞,直到有goroutine来接收数据。同样,如果通道中没有数据,接收操作也会阻塞,直到有数据被发送到通道。这种特性使得非缓冲通道不仅是数据传输的渠道,还是一个同步多个goroutine的强大工具。
基础介绍
非缓冲通道保证了数据传递的即时性,即数据发送后立即被接收。这种即时的数据交换机制意味着每个发送操作都必须有一个对应的接收操作准备接收数据,这种机制在并发编程中常用于控制不同goroutine之间的执行顺序。
下面的示例展示了如何使用非缓冲通道进行两个goroutine之间的同步通信。在这个例子中,我们将创建一个主goroutine和一个工作goroutine,主goroutine发送一个任务到工作goroutine,然后等待工作goroutine的处理结果。
package mainimport ("fmt""time"
)func worker(done chan bool) {fmt.Println("工作中...")time.Sleep(time.Second)fmt.Println("工作完成")// 发送一个值表示工作已经完成done <- true
}func main() {// 创建一个非缓冲的布尔型通道done := make(chan bool)// 启动一个工作goroutinego worker(done)// 等待工作goroutine的通知<-donefmt.Println("在主goroutine中继续执行")
}
程序解析
- 通道的创建和使用:我们通过
make(chan bool)创建了一个非缓冲的布尔型通道done。这个通道用来从工作goroutine向主goroutine发送任务完成的信号。 - 工作goroutine:
worker函数模拟长时间运行的任务,完成后通过done通道发送一个true值来通知主goroutine任务已完成。 - 主goroutine的阻塞等待:在主goroutine中,使用
<-done来阻塞主goroutine的执行,直到从done通道接收到工作完成的信号。
总结
非缓冲通道是Go语言中一种实现goroutine间同步通信的强大机制。通过确保每个发送操作都必须有一个对应的接收操作同时准备好,非缓冲通道可以精确控制数据的即时传递和goroutine的执行顺序。这种通道不仅是数据传输的渠道,也是协调并发操作的关键工具。通过非缓冲通道,Go程序能够以直接且同步的方式处理并发任务,从而保持高效和可靠的执行流程。简而言之,非缓冲通道是Go并发编程中不可或缺的同步神器
缓冲通道在Go语言中是一种允许在没有接收方准备好时进行数据传输的通信机制。这种通道通过内部缓冲区来暂存数据,从而允许发送操作在缓冲区未满时立即返回,而不必等待接收方。缓冲通道的存在极大地提升了并发程序的灵活性和效率,使得goroutine之间可以更加灵活地进行非阻塞通信和数据交换。
相关文章:
【Go】通道:缓冲通道和非缓冲通道
目录 通道的基本概念 缓冲通道 非缓冲通道 总结 通道的基本概念 在Go语言中,通道是一种特殊的类型,用于在goroutine之间传递数据。你可以将通道想象为数据的传输管道。通道分为两种类型: 非缓冲通道(Unbuffered Channels&…...
Java中数组的使用
在Java编程中,数组是一种非常重要的数据结构,它允许我们存储相同类型的多个元素。对于初学者来说,理解数组的基本概念、初始化、遍历、默认值以及内存分配和使用注意事项是非常关键的。 一、数组的概念 数组是一个可以容纳多个相同类型数据…...
CAP5_Monday
A Set to Max (Easy Version) 给定数组 a 和 b,可以执行以下操作任意次 : 让 a l ∼ a r a_l\sim a_r al∼ar 中的所有所有元素变成 a i a_i ai ( l ≤ i ≤ r ) (l\leq i\leq r) (l≤i≤r), 其中 1 ≤ l ≤ r ≤ n 1\leq l \leq r \leq n 1≤…...
科大讯飞星火开源大模型iFlytekSpark-13B GPU版部署方法
星火大模型的主页:iFlytekSpark-13B: 讯飞星火开源-13B(iFlytekSpark-13B)拥有130亿参数,新一代认知大模型,一经发布,众多科研院所和高校便期待科大讯飞能够开源。 为了让大家使用的更加方便,科…...
SpringBoot基于RabbitMQ实现消息延迟队列方案
知识小科普 在此之前,简单说明下基于RabbitMQ实现延时队列的相关知识及说明下延时队列的使用场景。 延时队列使用场景 在很多的业务场景中,延时队列可以实现很多功能,此类业务中,一般上是非实时的,需要延迟处理的&a…...
Go语言使用标准库时常见错误
Go的标准库是一组增加和拓展语言的核心包。然而,很容易误用标准库,或者我们对其行为理解有限,导致产生了bug或不应该在生产级应用程序中某些功能。 1. 提供错误的持续时间 标准库提供了获取 time.Duration 的常用函数和方法,但由于 time.Duration 是 int64 的自定义类型,…...
UE5不打包启用像素流 ubuntu22.04
首先查找引擎中像素流的位置: zkzk-ubuntu2023:/media/zk/Data/Linux_Unreal_Engine_5.3.2$ sudo find ./ -name get_ps_servers.sh [sudo] zk 的密码: ./Engine/Plugins/Media/PixelStreaming/Resources/WebServers/get_ps_servers.sh然后在指定路径中…...
Redis 常用数据类型常用命令和应用场景
首先先混个眼熟 Redis 中的 8 种常用数据类型: 5 种基础数据类型:String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合࿰…...
ins视频批量下载,instagram批量爬取视频信息
简介 Instagram 是目前最热门的社交媒体平台之一,拥有大量优质的视频内容。但是要逐一下载这些视频往往非常耗时。在这篇文章中,我们将介绍如何使用 Python 编写一个脚本,来实现 Instagram 视频的批量下载和信息爬取。 我们使用selenium获取目标用户的 HTML 源代码,并将其保存…...
Canvas图形编辑器-数据结构与History(undo/redo)
Canvas图形编辑器-数据结构与History(undo/redo) 这是作为 社区老给我推Canvas,于是我也学习Canvas做了个简历编辑器 的后续内容,主要是介绍了对数据结构的设计以及History能力的实现。 在线编辑: https://windrunnermax.github.io/CanvasEditor开源地…...
阿里云Centos7下编译glibc
编译glibc 原来glibc版本 编译前需要的环境: CentOS7 gcc 8.3.0 gdb 8.3.0 make 4.0 binutils 2.39 (ld -v) python 3.6.8 其他看INSTALL, 但有些版本也不易太高 wget https://mirrors.aliyun.com/gnu/glibc/glibc-2.37.tar.gz tar -zxf glibc-2.37.tar.gz cd glibc-2.37/ …...
UE5数字孪生系列笔记(四)
场景的切换 创建一个按钮的用户界面UMG 创建一个Actor,然后将此按钮UMG添加到组件Actor中 调节几个全屏的背景 运行结果 目标点切换功能制作 设置角色到这个按钮的位置效果 按钮被点击就进行跳转 多个地点的切换与旋转 将之前的目标点切换逻辑替换成旋转的逻…...
品牌故事化:Kompas.ai如何塑造深刻的品牌形象
在这个信息爆炸的时代,品牌故事化已经成为企业塑造独特形象、与消费者建立情感联系的重要手段。一个引人入胜的品牌故事不仅能够吸引消费者的注意力,还能够在消费者心中留下持久的印象,建立起强烈的情感连接。本文将深入探讨品牌故事化对于构…...
5g和2.4g频段有什么区别
运行的频段不同 2.4G和5G频段的主要区别在于它们运行的频段不同,2.4G频段运行在2.4GHz的频段上,而5G频段(这里指的是5GHz频段)运行在5GHz的频段上。12 这导致了两者在传输速度、覆盖范围、抗干扰能力等方面的明显差异。以下是详…...
交通管理在线服务系统|基于Springboot的交通管理系统设计与实现(源码+数据库+文档)
交通管理在线服务系统目录 目录 基于Springboot的交通管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户信息管理 2、驾驶证业务管理 3、机动车业务管理 4、机动车业务类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计…...
konva.js 工具类
konva.js 工具类 class KonvaCanvas {/*** 初始化画布* param {String} domId 容器dom id*/constructor(domId) {this.layer null;this.stage null;this.scale 1;this.init(domId);}/*** 聚焦到指定元素* param {String} elementId 元素dom id*/focusOn(elementId) {if (!t…...
php未能在vscode识别?
在设置里搜php,找到settings.json,设置你的安装路径即可。 成功...
解读MongoDB官方文档获取mongo7.0版本的安装步骤与基本使用
mongo式一款NOSQL数据库,用于存储非结构化数据,mongo是一种用于存储json的数据数据,可以通过mongo提供的命令解析json获取想要的值。 数据模型 了解关系数据库会很熟悉database,table,row,column的概念,分别是数据库,…...
【数据结构|C语言版】顺序表
前言1. 初步认识数据结构2. 线性表3. 顺序表3.1 顺序表的概念3.1 顺序表的分类3.2 动态顺序表的实现 结语 前言 各位小伙伴大家好!小编来给大家讲解一下数据结构中顺序表的相关知识。 1. 初步认识数据结构 【概念】数据结构是计算机存储、组织数据的⽅式。 数据…...
Unity类银河恶魔城学习记录12-17 p139 In game UI源代码
Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI.cs using UnityEngine;public class UI : MonoBehaviour {[SerializeFie…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
