当前位置: 首页 > news >正文

Golang 并发机制-3:通道(channels)机制详解

并发编程是一种创建性能优化且响应迅速的软件的强大方法。Golang(也称为 Go)通过通道(channels)这一特性,能够可靠且优雅地实现并发通信。本文将揭示通道的概念,解释其在并发编程中的作用,并提供有关如何通过无缓冲通道和有缓冲通道发送或接收数据的见解。

介绍通道

在Go语言中,通道是一个基本的特性,它支持在gooutine(并发执行线程)之间进行安全和同步的通信。它们充当管道,通过它可以在程序之间传递数据,促进并发程序中的协调和同步。

通道是单向的,这意味着它们既可以用于发送数据(<- chan)也可以用于接收数据(chan <- )。这种单向性有助于在程序间实现清晰和可控的数据流。
在这里插入图片描述

发送和接收数据

1. 非缓存通道

无缓冲通道是一种同时发送和接收数据的通道。当在无缓冲通道上发送值时,发送方将阻塞,直到有相应的接收方准备接收该数据。同样,接收器将阻塞,直到有可用的数据接收。

下面是一个说明使用非缓冲通道的示例:

package mainimport ("fmt""time"
)func main() {ch := make(chan int) // Create an unbuffered channelgo func() {ch <- 42 // Send data into the channel}()// time.Sleep(time.Second) // Give the Goroutine time to executevalue := <-ch // Receive data from the channelfmt.Println("Received:", value)
}

在这个例子中,一个线程将值 42发送到未缓冲的通道 ch.主线程接收它,程序将阻塞,直到发送方和接收方都准备好。

2. 缓存通道

缓冲通道支持使用指定的缓冲区大小异步发送和接收数据。这意味着只要缓冲区未满,就可以在不等待接收器的情况下向通道发送多个值。同样,只要缓冲区不是空的,接收方可以从通道中读取数据,而不需要等待发送方。

下面是一个使用缓冲通道的例子:

package mainimport "fmt"func main() {ch := make(chan string, 2) // Create a buffered channel with a capacity of 2ch <- "Hello" // Send data into the channelch <- "World"fmt.Println(<-ch) // Receive data from the channelfmt.Println(<-ch)
}

在本例中,我们创建了容量为2的缓冲通道ch。我们可以在不阻塞的情况下向通道发送两个值,然后接收并打印这些值。当你希望解耦发送方和接收方时,缓冲通道非常有用,允许它们在缓冲区大小约束下独立工作。

  • 同步通道

Go中的通道同步是一种技术,用于通过使用通道来协调和同步Goroutines(并发线程)的执行。通道促进了程序之间安全和有序的通信,允许它们在完成特定任务或准备好数据时相互发送信号。这种同步机制对于确保运行例程以受控和同步的方式执行至关重要。

下面是通道同步有用的一些常见场景:

  1. 等待Goroutines完成:你可以使用通道来等待一个或多个Goroutines在继续主程序之前完成它们的任务。
  2. 协调并行任务:通道可用于协调并发执行任务的多个goroutine,确保它们以特定顺序完成工作或在特定点同步。
  3. 收集结果:通道可用于收集和聚合来自多个goroutine的结果,然后在所有goroutine完成其工作后处理它们。

让我们用例子来探索这些场景:

  • 等待goroute完成
package mainimport ("fmt""sync"
)func worker(id int, wg *sync.WaitGroup) {defer wg.Done()fmt.Printf("Worker %d is working\n", id)
}func main() {var wg sync.WaitGroupfor i := 1; i <= 3; i++ {wg.Add(1)go worker(i, &wg)}wg.Wait() // Wait for all workers to finishfmt.Println("All workers have finished.")
}

在这个例子中,我们有三个工作程序。我们使用“同步”。WaitGroup’,等待所有工人完成他们的工作,然后打印“所有工人都完成了”。

  • 协同并行任务
package mainimport ("fmt""sync"
)func main() {var wg sync.WaitGroupch := make(chan int)for i := 1; i <= 3; i++ {wg.Add(1)go func(id int) {defer wg.Done()fmt.Printf("Goroutine %d is working\n", id)ch <- id // Send a signal to the channel when done}(i)}// Wait for all Goroutines to signal completiongo func() {wg.Wait()close(ch) // Close the channel when all Goroutines are done}()for id := range ch {fmt.Printf("Received signal from Goroutine %d\n", id)}fmt.Println("All Goroutines have finished.")
}

在本例中,我们有三个执行工作并使用通道发出完成信号的goroutine。我们使用“同步”。WaitGroup '等待所有的Goroutine完成,并且一个单独的Goroutine侦听通道以知道每个Goroutine何时完成其工作。

  • 收集结果
package mainimport ("fmt""sync"
)func worker(id int, resultChan chan<- int, wg *sync.WaitGroup) {defer wg.Done()result := id * 2resultChan <- result // Send the result to the channel
}func main() {var wg sync.WaitGroupresultChan := make(chan int, 3)for i := 1; i <= 3; i++ {wg.Add(1)go worker(i, resultChan, &wg)}wg.Wait() // Wait for all workers to finishclose(resultChan) // Close the channel when all results are sentfor result := range resultChan {fmt.Printf("Received result: %d\n", result)}
}

在本例中,三个工作线程程序计算结果并将其发送到通道。主程序等待所有工作线程完成,关闭通道,然后从通道读取和处理结果。

这些示例说明了如何使用通道同步来协调和同步Go中各种并发编程场景中的Go例程。通道为线程间安全有序的通信提供了强大的机制,使编写行为可预测且可靠的并发程序变得更加容易。

Select 语句: 多路复用通道(Multiplexing Channels)

管理并发任务的关键工具之一是“select”语句。在本文中,我们将探讨“select”语句在多路复用通道中的作用,这是一种使Go程序员能够有效地同步和协调Go例程的技术。

当你有多个通过各种渠道进行通信的goroutine时,可能需要有效地协调它们的活动。“select”语句支持通过选择首个可以处理的通道操作来实现这一点。

下面是一个简单的例子,演示了在多路信道中使用“select”:

package mainimport ("fmt""time"
)func main() {ch1 := make(chan string)ch2 := make(chan string)go func() {time.Sleep(time.Second)ch1 <- "Message from Channel 1"}()go func() {time.Sleep(time.Millisecond * 500)ch2 <- "Message from Channel 2"}()select {case msg1 := <-ch1:fmt.Println(msg1)case msg2 := <-ch2:fmt.Println(msg2)}fmt.Println("Main function exits")
}

在本例中,我们有两个在两个不同通道上发送消息的goroutine, ch1 ch2 select语句选择可用的首个通道操作,允许我们从 ch1 ch2接收和打印消息。然后,程序继续执行main函数,演示使用“select”的通道复用功能。

  • select 带缺省分支

‘ select ’语句还支持‘ default ’情况,当您想要处理没有通道操作准备好的情况时,这很有用。这里有一个例子:

package mainimport ("fmt""time"
)func main() {ch := make(chan string)go func() {time.Sleep(time.Second * 2)ch <- "Message from Channel"}()select {case msg := <-ch:fmt.Println(msg)default:fmt.Println("No message received")}fmt.Println("Main function exits")
}

在本例中,我们有一个在通道‘ ch ’上发送消息的程序。然而,“select”语句包含一个“default”情况,用于处理在预期时间内没有消息到达的情况。这允许在没有任何通道操作就绪的情况下进行优雅的处理。

Go中的最佳实践和模式:扇出、扇入和关闭通道

当谈到编写干净高效的Go代码时,有一些最佳实践和模式可以显著提高并发程序的质量和性能。在本文中,我们将探讨两个基本实践:Fan-out, Fan-in(扇出、扇入)和关闭通道。这些模式是在Go应用程序中管理并发性和通信的强大工具。

在这里插入图片描述
在这里插入图片描述
  1. 扇出,扇入

Fan-out, Fan-in模式是一种并发设计模式,允许你跨多个goroutine分发工作,然后收集和合并结果。当处理可以并发处理然后进行聚合的任务时,此模式特别有用。

  • 扇出,扇入示例
package mainimport ("fmt""math/rand""sync""time"
)func worker(id int, input <-chan int, output chan<- int) {for number := range input {// Simulate some worktime.Sleep(time.Millisecond * time.Duration(rand.Intn(100)))output <- number * 2}
}func main() {rand.Seed(time.Now().UnixNano())input := make(chan int)output := make(chan int)const numWorkers = 3var wg sync.WaitGroup// Fan-out: Launch multiple workersfor i := 0; i < numWorkers; i++ {wg.Add(1)go func(id int) {defer wg.Done()worker(id, input, output)}(i)}// Fan-in: Collect resultsgo func() {wg.Wait()close(output)}()// Send data to workersgo func() {for i := 1; i <= 10; i++ {input <- i}close(input)}()// Receive and process resultsfor result := range output {fmt.Println("Result:", result)}
}

在本例中,我们创建了三个worker goroutine,它们执行一些模拟工作,然后将结果发送到输出通道。主程序生成输入数据,单独的程序使用扇入模式收集和处理结果。

  1. 关闭通道

关闭通道是发送数据传输完成信号和防止程序无限阻塞的基本做法。当你不再打算通过通道发送数据时,关闭通道以避免死锁是至关重要的。

package mainimport "fmt"func main() {dataChannel := make(chan int, 3)go func() {defer close(dataChannel) // Close the channel when donefor i := 1; i <= 3; i++ {dataChannel <- i}}()// Receive data from the channelfor num := range dataChannel {fmt.Println("Received:", num)}
}

在本例中,我们创建了一个容量为3的缓冲通道‘ dataChannel ’。在向通道发送三个值之后,我们使用‘ close ’函数关闭它。关闭任何接收器的通道信号,不再发送数据。这允许接收程序在处理完所有数据后优雅地退出。

相关文章:

Golang 并发机制-3:通道(channels)机制详解

并发编程是一种创建性能优化且响应迅速的软件的强大方法。Golang&#xff08;也称为 Go&#xff09;通过通道&#xff08;channels&#xff09;这一特性&#xff0c;能够可靠且优雅地实现并发通信。本文将揭示通道的概念&#xff0c;解释其在并发编程中的作用&#xff0c;并提供…...

kamailio的kamctl的使用

kamctl 是 Kamailio SIP 服务器的管理工具&#xff0c;用于执行各种管理任务&#xff0c;如启动、停止、重启 Kamailio 进程&#xff0c;管理用户、ACL、路由、信任的 IP 地址等。以下是对 kamctl 命令的解释及举例说明&#xff1a; 1. 启动、停止、重启 Kamailio start: 启动…...

HarmonyOS:ArkWeb进程

ArkWeb是多进程模型,分为应用进程、Web渲染进程、Web GPU进程、Web孵化进程和Foundation进程。 说明 Web内核没有明确的内存大小申请约束,理论上可以无限大,直到被资源管理释放。 ArkWeb进程模型图 应用进程中Web相关线程(应用唯一) 应用进程为主进程。包含网络线程、Vi…...

UI线程用到COM只能选单线程模型

无论用不用UI库&#xff0c;哪怕是用Win32 API手搓UI&#xff0c;UI线程要用COM的话&#xff0c;必须初始化为单线程单元(STA)&#xff0c;即CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);&#xff0c;不能用MULTITHREADTHREADED。 实际上&#xff0c;很多(WPF等)UI库若…...

LLMs之DeepSeek:Math-To-Manim的简介(包括DeepSeek R1-Zero的详解)、安装和使用方法、案例应用之详细攻略

LLMs之DeepSeek&#xff1a;Math-To-Manim的简介(包括DeepSeek R1-Zero的详解)、安装和使用方法、案例应用之详细攻略 目录 Math-To-Manim的简介 1、特点 2、一个空间推理测试—考察不同大型语言模型如何解释和可视化空间关系 3、DeepSeek R1-Zero的简介&#xff1a;处理更…...

在C语言中使用条件变量实现线程同步

互斥量、原子操作都是实现线程同步的方法&#xff0c;今日介绍使用条件变量来实现线程同步。在多线程应用中&#xff0c;当某个线程的执行依赖于另一个线程对数据的处理时&#xff0c;这个线程可能没有被阻塞&#xff0c;只是不断地检查某个条件是否成立了&#xff08;这个条件…...

图书管理系统 Axios 源码__新增图书

目录 功能介绍 核心代码解析 源码&#xff1a;新增图书功能 总结 本项目基于 HTML、Bootstrap、JavaScript 和 Axios 开发&#xff0c;实现了图书的增删改查功能。以下是新增图书的功能实现&#xff0c;适合前端开发学习和项目实践。 功能介绍 用户可以通过 模态框&#xf…...

Maven全解析:从基础到精通的实战指南

概念&#xff1a; Maven 是跨平台的项目管理工具。主要服务基于 Java 平台的构建&#xff0c;依赖管理和项目信息管理项目构建&#xff1a;高度自动化&#xff0c;跨平台&#xff0c;可重用的组件&#xff0c;标准化的流程 依赖管理&#xff1a; 对第三方依赖包的管理&#xf…...

数据密码解锁之DeepSeek 和其他 AI 大模型对比的神秘面纱

本篇将揭露DeepSeek 和其他 AI 大模型差异所在。 目录 ​编辑 一本篇背景&#xff1a; 二性能对比&#xff1a; 2.1训练效率&#xff1a; 2.2推理速度&#xff1a; 三语言理解与生成能力对比&#xff1a; 3.1语言理解&#xff1a; 3.2语言生成&#xff1a; 四本篇小结…...

python算法和数据结构刷题[5]:动态规划

动态规划&#xff08;Dynamic Programming, DP&#xff09;是一种算法思想&#xff0c;用于解决具有最优子结构的问题。它通过将大问题分解为小问题&#xff0c;并找到这些小问题的最优解&#xff0c;从而得到整个问题的最优解。动态规划与分治法相似&#xff0c;但区别在于动态…...

Ollama+OpenWebUI部署本地大模型

OllamaOpenWebUI部署本地大模型 前言 Ollama是一个强大且易于使用的本地大模型推理框架&#xff0c;它专注于简化和优化大型语言模型&#xff08;LLMs&#xff09;在本地环境中的部署、管理和推理工作流。可以将Ollama理解为一个大模型推理框架的后端服务。 Ollama Ollama安…...

Python从0到100(八十六):神经网络-ShuffleNet通道混合轻量级网络的深入介绍

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…...

【网络】传输层协议TCP(重点)

文章目录 1. TCP协议段格式2. 详解TCP2.1 4位首部长度2.2 32位序号与32位确认序号&#xff08;确认应答机制&#xff09;2.3 超时重传机制2.4 连接管理机制(3次握手、4次挥手 3个标志位)2.5 16位窗口大小&#xff08;流量控制&#xff09;2.6 滑动窗口2.7 3个标志位 16位紧急…...

海思ISP开发说明

1、概述 ISP&#xff08;Image Signal Processor&#xff09;图像信号处理器是专门用于处理图像信号的硬件或处理单元&#xff0c;广泛应用于图像传感器&#xff08;如 CMOS 或 CCD 传感器&#xff09;与显示设备之间的信号转换过程中。ISP通过一系列数字图像处理算法完成对数字…...

实验十 Servlet(一)

实验十 Servlet(一) 【实验目的】 1&#xff0e;了解Servlet运行原理 2&#xff0e;掌握Servlet实现方式 【实验内容】 1、参考课堂例子&#xff0c;客户端通过login.jsp发出登录请求&#xff0c;请求提交到loginServlet处理。如果用户名和密码相同则视为登录成功&#xff0c…...

doris:聚合模型的导入更新

这篇文档主要介绍 Doris 聚合模型上基于导入的更新。 整行更新​ 使用 Doris 支持的 Stream Load&#xff0c;Broker Load&#xff0c;Routine Load&#xff0c;Insert Into 等导入方式&#xff0c;往聚合模型&#xff08;Agg 模型&#xff09;中进行数据导入时&#xff0c;都…...

Java NIO_非阻塞I/O的实现与优化

1. 引言 1.1 背景介绍 随着互联网应用的快速发展,传统的阻塞I/O模型已经无法满足高并发、高性能的需求。Java NIO(Non-blocking I/O)提供了高效的非阻塞I/O操作,使得开发者能够构建高性能的网络应用和文件处理系统。 1.2 Java NIO的重要性 Java NIO通过非阻塞I/O和多路…...

代码随想录算法训练营Day51 | 101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿

文章目录 101.孤岛的总面积思路与重点 102.沉没孤岛思路与重点 103.水流问题思路与重点 104.建造最大岛屿思路与重点 101.孤岛的总面积 题目链接&#xff1a;101.孤岛的总面积讲解链接&#xff1a;代码随想录状态&#xff1a;直接看题解了。 思路与重点 nextx或者nexty越界了…...

Games202Lecture 6 Real-time Environment Mapping

RTRT RTRT&#xff08;real time ray tracing): path tracingdenoising PRT PRT (Precomputed radiance transfer):离线预计算&#xff0c;运行时快速内积。 预计算&#xff08;Offline Precomputation&#xff09;&#xff1a; 传输函数&#xff08;Transfer Function&…...

在 Zemax 中使用布尔对象创建光学光圈

在 Zemax 中&#xff0c;布尔对象用于通过组合或减去较简单的几何形状来创建复杂形状。布尔运算涉及使用集合运算&#xff08;如并集、交集和减集&#xff09;来组合或修改对象的几何形状。这允许用户在其设计中为光学元件或机械部件创建更复杂和定制的形状。 本视频中&#xf…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...