Go语言中的通道 (Channel) 实践:Goroutine之间的通信

news2024/10/13 4:15:48

1. 引言

在Go语言中,并发编程是其核心优势之一。与其他编程语言不同,Go语言推荐使用通道 (Channel) 来进行多线程或并发任务的协调与通信,而非使用锁机制。本文将介绍如何通过通道在多个goroutine之间进行通信,避免竞争条件和复杂的锁机制。

2. 为什么选择通道

在多线程编程中,传统的方式通常是通过显式锁或条件变量来解决多个线程同时访问共享资源的问题。虽然这种方法有效,但容易导致复杂的竞争条件和死锁。Go语言引入了通道 (Channel) 的概念,它允许开发者通过消息传递来共享信息,从而减少对共享内存和锁的需求。

2.1 通道的基本概念

通道提供了一种并发执行的函数之间通过发送和接收指定元素类型的值进行通信的机制。通道是一种类型安全的数据结构,确保发送和接收的数据类型一致。

未初始化的通道值为 nil,因此在使用之前需要通过 make() 函数进行初始化。

var ch chan int
ch = make(chan int)

通过通道发送数据:

ch <- 1

从通道接收数据:

data := <-ch

2.2 通道的特性

通道是 Go语言的核心并发模型之一,它具有以下特性:

  • 同步特性:通道本身是同步的,意味着同一时间只能有一个 goroutine 操作通道,这有效地避免了多线程竞争。
  • 阻塞特性:在通道中发送或接收数据时,操作会被阻塞,直到另外一个 goroutine 完成对应的接收或发送操作。

3. 实现 Goroutine 之间的通信

下面通过一个实际的例子来展示如何通过通道在 goroutine 之间进行通信:

3.1 示例代码

package main

import (
	"fmt"
	"time"
)

// 在一个 goroutine 中发送信息到主线程
func main() {
	// 定义一个布尔类型的通道
	var ch chan bool = make(chan bool)

	// 启动一个 goroutine 进行任务
	go func() {
		for i := 0; i < 10; i++ {
			fmt.Println("goroutine-", i)
		}
		// 模拟一些任务延迟
		time.Sleep(time.Second * 1)
		// 在任务完成后,通过通道向主线程发送完成信号
		ch <- true
	}()

	// 主线程阻塞等待来自通道的信号
	data := <-ch
	fmt.Println("主线程接收到通道数据:", data)
}

3.2 输出结果

当我们运行这段代码时,主线程会启动一个新的 goroutine,并让它执行一个循环打印任务。goroutine 完成任务后,通过通道向主线程发送一个布尔值信号。主线程则会一直阻塞等待,直到接收到这个信号:

goroutine-: 0
goroutine-: 1
goroutine-: 2
goroutine-: 3
goroutine-: 4
goroutine-: 5
goroutine-: 6
goroutine-: 7
goroutine-: 8
goroutine-: 9
主线程接收到通道数据: true

3.3 代码解析

  1. 通道的创建:通过 make(chan bool) 创建一个布尔类型的通道,用于通信。
  2. 启动 goroutine:使用 go 关键字启动一个匿名函数,在其中执行打印操作。
  3. 任务完成信号:在 goroutine 中完成任务后,将 true 发送到通道 ch
  4. 主线程等待:主线程通过 <-ch 操作阻塞等待,直到接收到通道中的数据,解除阻塞继续执行。

4. 通道的常见使用场景

4.1 任务同步

通过通道可以很方便地实现不同 goroutine 之间的任务同步。例如,在一个并发任务完成后,通知主线程继续处理后续逻辑。

4.2 数据传递

通道还可以用于在 goroutine 之间传递复杂数据,如结构体、数组等,避免使用全局变量或者锁机制。

4.3 任务分发

通道可以作为任务队列,多个 goroutine 从通道中读取任务并并发处理。

5. 总结

在 Go 语言中,通道(Channel)为我们提供了一种优雅的并发编程方式。相比于传统的锁机制,通道通过消息传递来解决多线程间的协作问题,避免了竞争条件和复杂的同步控制。它不仅让代码更易于理解和维护,还提高了程序的性能和可靠性。


更多内容:

  • Go语言官方文档
  • Go并发模式介绍

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

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

相关文章

基于Springboot+Vue的医疗废物管理系统 (含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 在系统…

基于yolov8、yolov5的交通标志检测识别系统(含UI界面、Python代码、数据集)

项目介绍 项目中所用到的算法模型和数据集等信息如下&#xff1a; 算法模型&#xff1a;     yolov8、yolov8 SE注意力机制 或 yolov5、yolov5 SE注意力机制 &#xff0c; 直接提供最少两个训练好的模型。模型十分重要&#xff0c;因为有些同学的电脑没有 GPU&#xff0…

避免 Python 类型转换错误:实用指南

在 Python 中&#xff0c;变量的类型是明确的&#xff0c;不能在没有显式转换的情况下直接将一种类型的值赋给另一种不同类型的变量。例如&#xff0c;以下将字符串与整数直接相加会报错&#xff0c;这跟其它语言有所差异&#xff0c;其它语言会进行隐式转 a "5" b…

c++类与对象三

C类与对象三 上期我们介绍了类的实例化&#xff0c;大小计算&#xff0c;还有this指针。这期我们继续深入更高层次的用法 类的六个默认函数 如个一个类里面没有成员&#xff0c;就是空类&#xff0c;但是空类里面真的什么都没有吗&#xff0c;并不是&#xff0c;在编译器中&…

大数据新视界 --大数据大厂之大数据环境下的零信任安全架构:构建可靠防护体系

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

Javascript 仅允许在异步函数和模块顶级使用 “await“

这个错误的原因&#xff0c;是我们在一个普通函数里调用了async函数&#xff0c;因为async 函数是异步函数&#xff0c;它返回一个 Promis&#xff0c;await必须与async一同出现。所以这里普通函数无法调用它。 async和await只是使函数调用看起来像同步而已&#xff0c;比如下…

【MMMLP】核心方法解读

此方法用于顺序推荐&#xff0c;和我的研究方向不一样&#xff0c;所以这里只探讨值得借鉴的部分 abstract&#xff1a; 现有的顺序推荐方法要么不能直接处理多模态&#xff0c;要么计算量大。为了解决这个问题&#xff0c;我们提出了一种新的多模态多层感知器&#xff08;MM…

MYSQL-windows安装配置两个或多个版本MYSQL

安装第一个mysql很简单&#xff0c;这里不再赘述。主要说说第二个怎么安装&#xff0c;服务怎么配置。 1. 从官网下载第二个MySQL并安装 一般都是免安装版了&#xff0c;下载解压到某个文件目录下(路径中尽量不要带空格或中文)&#xff0c;再新建一个my.ini文件&#xff08;或…

QGroundControl最新版本MacOS平台编译(使用CMakeLists.txt)

1.下载源码: git clone https://github.com/mavlink/qgroundcontrol.git --recursive 2.安装依赖: brew install GStreamer 设置环境变量:GST_PLUGIN_PATH 安装SDL2: brew install SDL2

C#自定义特性

特性的用处 一般用来影响某一个类的个别字段或者方法 定义特性 需要将类继承Attribute 可以通过构造函数的方式影响使用特性的方法 可以通过给自定义的特性通过加AttributeUsage特性的方法进行进一步管理 AttributeUsage特性默认传三个参数 第一个参数一般用来约束此自定义…

怎么把m4a转换成mp3?8种关于m4a转成MP3格式的转换方法

怎么把m4a转换成mp3&#xff1f;尽管m4a格式在音质上表现突出&#xff0c;但并不是所有设备和软件都能支持&#xff0c;给一些用户带来了不便。为了保证音乐文件能够在更多设备和平台上播放&#xff0c;许多人选择将m4a转换为MP3格式。MP3几乎可以在所有播放器和设备上使用&…

LeetCode讲解篇之2320. 统计放置房子的方式数

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 我们首先发现一个规律街道两侧是否放置房子是独立的&#xff0c;即放置房子的方式数 一侧放置房子的方式数 * 另一侧放置房子的方案数 一侧放置房子的方式数的二次方 对于一侧[0, i]范围内地块放置房子的方式…

starrocks-删除表字段

1、背景 之前做了个大宽表&#xff0c;将近100个字段&#xff0c;但是后来发现很多字段在实际生产上都没有用到&#xff0c;并且随着数据量的增加&#xff0c;给集群的存储以及消费任务的解析带来了比较大的压力。所以决定对字段做删除处理。 当前的表是使用routine load任务从…

渗透测试 之 AD域渗透 【AS-REP Roasting】 攻击技术详解

说明: AS-REP Roasting是一种对用户账户进行离线爆破的攻击方式。但是该攻击方式使用比较受限&#xff0c;因为其需要用户账户设置“不要求Kerberos预身份验证”选项&#xff0c;而该选项默是没有勾选的。Kerberos 预身份验证发生在Kerberos身份验证的第一阶段&#xff08;AS_…

14. 最长公共前缀【字符串】

文章目录 14. 最长公共前缀解题思路Go代码 14. 最长公共前缀 14. 最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 ""。 示例 1&#xff1a; 输入&#xff1a;strs ["flower","flow&…

STM32 QSPI接口驱动GD/W25Qxx配置简要

STM32 QSPI接口GD/W25Qxx配置简要 &#x1f4dd;本篇会具体涉及介绍Winbond&#xff08;华邦&#xff09;和GD(兆易创新) NOR flash相关型号指令差异。由于网络上可以搜索到很多相关QSPI相关知识内容&#xff0c;不对QSPI通讯协议做深度解析。 &#x1f516;首先确保所使用的ST…

2022年10月自考《数据库系统原理》04735试题

目录 一.单选题 二.填空题 三.设计题 四.简答题 五.综合题 一.单选题 1.数据库系统管理员的英文缩写是 (书中)P29页 A.Data B.DB C.DBA D.DBS 2.客户/服务器模式中&#xff0c;客户端和服务器可以同时工作在同一台计算机上&#xff0c;该方式称为 (书中)P37页 A.单机方…

使用Copilot自动在Rstudio中写代码,提高效率!

原文链接&#xff1a;使用Copilot自动在Rstudio中写代码&#xff0c;提高效率&#xff01; 2022年教程总汇 2023年教程总汇 引言 今天我们分享&#xff0c;在Rstuido中使用copilot自动写代码&#xff0c;提高你的分析和绘图效率。 copilot是2024年9月后引入到Rstuido中&…

如何在 IDEA 中导入 Java 项目的 Git 仓库并启动

目录 前言1. 从 Git 仓库导入 Java 项目2. 配置 Maven2.1 配置 Maven 仓库和设置文件2.2 加载依赖 3. 配置 Tomcat 并运行项目3.1 配置 Tomcat3.2 配置 Server URL3.3 启动项目 4. 常见问题与解决方法4.1 Maven 依赖无法下载4.2 Tomcat 部署失败4.3 项目启动后无法访问 结语 前…

从RNN讲起——序列数据处理网络

文章目录 RNN&#xff08;Recurrent Neural Network&#xff0c;循环神经网络&#xff09;1. 什么是RNN&#xff1f;2. 经典RNN的结构3. RNN的主要特点4. RNN存在问题——长期依赖&#xff08;Long-TermDependencies&#xff09;问题 LSTM&#xff08;Long Short-Term Memory&a…