Go新手步步为赢:并发编程通信指南

简介: Go新手步步为赢:并发编程通信指南

概述

Go 语言在并发通信方面有着独特的 CSP 并发模型。

Go 语言主要通过 Channel 实现 Goroutine 间通信,也支持共享内存和原子操作方式。

本文将通过示例阐述 Go 语言的各种并发通信方式。

主要内容包括

并发通信机制

Channel 通信详解

共享内存通信

原子操作通信

通信方式选用指南

Channel 通信示例


 

一、并发通信机制

Go 语言支持以下三种 Goroutine 间通信方式:

Channel 通信:Goroutine 间传递消息和数据

共享内存:通过内存共享指定数据

原子操作:利用原子操作的同步效应

每种方式都有明确的使用场景,应根据具体需求选择合适的通信方式。


 

二、Channel 通信详解

Channel 是 Go 语言内置的 goroutine 间同步通信机制。可以通过 Channel 在多个 goroutine 间传递消息或数据。

1. 创建方式

使用 make 创建 Channel



ch := make(chan int) //无缓冲区Channelch := make(chan int, 100) //有缓冲Channel

2. 数据传输

通过操作符<-向 Channel 发送或接收数据



ch <- 10 // 发送数据到Channelx := <- ch // 从Channel接收数据

3. 关闭 Channel

可以通过内置 close 函数关闭 Channel


close(ch)

4. 选择器

可以通过 select 选择多个 Channel 的通信


select {  case <-ch1:    // 操作ch1  case <-ch2:      // 操作ch2  default:    // 默认操作}

5. 常见通信方式

Channel 支持多种通信方式:

同步返回值

发布-订阅

工作池


 

三、共享内存通信

Go 程序也可以通过共享内存进行通信:

1.

// Counter包
var Value int // 共享变量
func SetValue(v int) {  Value = v // 写入共享变量 } 
func ReadValue() int {  return Value // 读取共享变量}

2. 并发安全数据结构

Go 标准库提供了许多并发安全的数据结构,如 sync.Map


var sMap sync.Map
sMap.Store("key", value) // 写入数据v, _ := sMap.Load("key") // 读取数据

这类数据结构利用内部锁保证并发安全。

3. 自定义共享数据

可以通过内置原子函数从零开始构建共享数据


type atomicInt struct {  val int32}
func (a *atomicInt) Increase() {  atomic.AddInt32(&a.val, 1)}
func (a *atomicInt) Value() int32 {  return atomic.LoadInt32(&a.val) }


 

四、原子操作通信

Go 语言提供了原子操作函数,可以被用来进行原子通信


import "sync/atomic"
var flag int32 
func wait() {  for atomic.LoadInt32(&flag) == 0 {     runtime.Gosched()  }}
func notify() {  atomic.StoreInt32(&flag, 1) }

利用原子操作的同步效应实现 Goroutine 间通知等待。

原子函数列表:

atomic.SwapInt32

atomic.CompareAndSwapInt32

atomic.AddInt32

atomic.LoadInt32

atomic.StoreInt32


 

五、通信方式选用指南

不同的通信方式各有优劣:

Channel

天然同步机制

编译期检测

只适合短小消息

共享内存

适合任意数据

必须使用同步原语

存在竞争风险

原子操作

最低层次通信

必须自己实现同步逻辑

可构建高级通信方式

根据具体场景需求,比如性能、频率、数量、分布式等方面来选择最合适的通信方式。


 

六、Channel 通信示例

1.

func worker(in, out chan *Task) {  for {    t := <-in    // 处理t    out<- t  }}
func CreateWorkerPool(num int) {  in := make(chan *Task)   out := make(chan *Task)
  // 启动goroutine  for i:= 0; i < num; i++ {     go worker(in, out)   }
  return in, out}

2.

type Hub struct {  subs map[chan<- int]bool}
func (h *Hub) subscribe() chan<- int {  ch := make(chan int)  h.subs[ch] = true  return ch}
func (h *Hub) broadcast(msg int) {  for sub := range h.subs {    sub <- msg  }}


 

总结

Go 语言内置了丰富的通信方式,包括 Channel、共享内存和原子操作,每种方式都有明确的应用场景

Channel 在不同 Goroutine 间传递消息和数据,它是 Go 的默认选择。

共享内存可以在 Goroutine 间直接共享数据,但需要控制并发访问。

原子操作提供了最底层的通信方式,需要自己实现同步逻辑。

选择合适的通信方式很重要,需要根据具体问题的并发模式、性能需求、数据量等方面进行决策。

充分理解和运用这些通信机制,可以设计出简洁高效的 Go 语言并发程序。

目录
相关文章
|
9月前
|
数据采集 安全 Go
Go 语言并发编程基础:Goroutine 的创建与调度
Go 语言的 Goroutine 是轻量级线程,由 runtime 管理,具有启动快、占用小、支持高并发的特点。本章介绍 Goroutine 的基本概念、创建方式(如使用 `go` 关键字或匿名函数)、M:N 调度模型及其工作流程,并探讨其在高并发场景中的应用,帮助理解其高效并发的优势。
|
9月前
|
Go 开发者
Go 并发编程基础:无缓冲与有缓冲通道
本章深入探讨Go语言中通道(Channel)的两种类型:无缓冲通道与有缓冲通道。无缓冲通道要求发送和接收必须同步配对,适用于精确同步和信号通知;有缓冲通道通过内部队列实现异步通信,适合高吞吐量和生产者-消费者模型。文章通过示例对比两者的行为差异,并分析死锁风险及使用原则,帮助开发者根据场景选择合适的通道类型以实现高效并发编程。
|
并行计算 安全 Go
Go语言中的并发编程:掌握goroutines和channels####
本文深入探讨了Go语言中并发编程的核心概念——goroutine和channel。不同于传统的线程模型,Go通过轻量级的goroutine和通信机制channel,实现了高效的并发处理。我们将从基础概念开始,逐步深入到实际应用案例,揭示如何在Go语言中优雅地实现并发控制和数据同步。 ####
|
11月前
|
存储 算法 物联网
解析局域网内控制电脑机制:基于 Go 语言链表算法的隐秘通信技术探究
数字化办公与物联网蓬勃发展的时代背景下,局域网内计算机控制已成为提升工作效率、达成设备协同管理的重要途径。无论是企业远程办公时的设备统一调度,还是智能家居系统中多设备间的联动控制,高效的数据传输与管理机制均构成实现局域网内计算机控制功能的核心要素。本文将深入探究 Go 语言中的链表数据结构,剖析其在局域网内计算机控制过程中,如何达成数据的有序存储与高效传输,并通过完整的 Go 语言代码示例展示其应用流程。
218 0
|
存储 Go 开发者
Go语言中的并发编程与通道(Channel)的深度探索
本文旨在深入探讨Go语言中并发编程的核心概念和实践,特别是通道(Channel)的使用。通过分析Goroutines和Channels的基本工作原理,我们将了解如何在Go语言中高效地实现并行任务处理。本文不仅介绍了基础语法和用法,还深入讨论了高级特性如缓冲通道、选择性接收以及超时控制等,旨在为读者提供一个全面的并发编程视角。
347 50
|
安全 Serverless Go
Go语言中的并发编程:深入理解与实践####
本文旨在为读者提供一个关于Go语言并发编程的全面指南。我们将从并发的基本概念讲起,逐步深入到Go语言特有的goroutine和channel机制,探讨它们如何简化多线程编程的复杂性。通过实例演示和代码分析,本文将揭示Go语言在处理并发任务时的优势,以及如何在实际项目中高效利用这些特性来提升性能和响应速度。无论你是Go语言的初学者还是有一定经验的开发者,本文都将为你提供有价值的见解和实用的技巧。 ####
|
算法 安全 程序员
Go语言的并发编程:深入理解与实践####
本文旨在探讨Go语言在并发编程方面的独特优势及其实现机制,通过实例解析关键概念如goroutine和channel,帮助开发者更高效地利用Go进行高性能软件开发。不同于传统的摘要概述,本文将以一个简短的故事开头,引出并发编程的重要性,随后详细阐述Go语言如何简化复杂并发任务的处理,最后通过实际案例展示其强大功能。 --- ###
|
Go 开发者
Go语言中的并发编程:掌握goroutines和channels####
本文深入探讨了Go语言中并发编程的核心概念,重点介绍了goroutines和channels的工作原理及其在实际开发中的应用。文章通过实例演示如何有效地利用这些工具来编写高效、可维护的并发程序,旨在帮助读者理解并掌握Go语言在处理并发任务时的强大能力。 ####
|
安全 Go 数据处理
Go语言中的并发编程:掌握goroutine和channel的艺术####
本文深入探讨了Go语言在并发编程领域的核心概念——goroutine与channel。不同于传统的单线程执行模式,Go通过轻量级的goroutine实现了高效的并发处理,而channel作为goroutines之间通信的桥梁,确保了数据传递的安全性与高效性。文章首先简述了goroutine的基本特性及其创建方法,随后详细解析了channel的类型、操作以及它们如何协同工作以构建健壮的并发应用。此外,还介绍了select语句在多路复用中的应用,以及如何利用WaitGroup等待一组goroutine完成。最后,通过一个实际案例展示了如何在Go中设计并实现一个简单的并发程序,旨在帮助读者理解并掌
|
安全 Java Go
Go语言中的并发编程:掌握goroutine与通道的艺术####
本文深入探讨了Go语言中的核心特性——并发编程,通过实例解析goroutine和通道的高效使用技巧,旨在帮助开发者提升多线程程序的性能与可靠性。 ####