Go语言的并发、协调创建和通信机制

1.并发

并发模型一般有四种,分别是多进程编程、多线程编程、非阻塞异步I/O编程和基于协调的编程

多进程编程

多进程编程利用操作系统的进程管理能力,每个进程拥有独立的内存空间和系统资源。进程间通信(IPC)需要通过特定机制(如管道、共享内存、消息队列)实现。适用于CPU密集型任务,能充分利用多核优势,但创建和切换开销较大。

多线程编程

多线程编程在单个进程内创建多个执行流,共享同一内存空间。线程切换成本低于进程,适合I/O密集型任务。需注意线程安全问题(如竞态条件、死锁)。全局解释器锁(GIL)在部分语言(如Python)中会限制多线程的并行效率。

非阻塞异步I/O编程

通过事件循环和回调机制处理并发,单线程即可管理大量I/O操作。当I/O未就绪时立即返回,避免线程阻塞。典型实现包括Node.js的EventEmitter、Python的asyncio。适合高并发网络服务,但对CPU密集型任务效果有限。

基于协调的编程

以协程(Coroutine)为核心,通过用户态调度实现协作式多任务。协程主动让出执行权而非被系统抢占,切换开销极低。常见于Go语言的goroutine、Python的generator。需开发者显式处理协程调度,适合高吞吐量场景。

2.并发与并行

并发是指同一时刻只能有一条指令执行,但多个进程指令被快速地轮换执行,达到宏观上有多个进程同时执行的效果

并行是指在同一时刻,有多条指令在多个处理器上同时执行

并发与并行的区别:

记住一句核心口诀并发:交替执行(同一 CPU,来回切换) 并行:同时执行(多个 CPU,一起干活)

通俗大白话解释就是

  1. 并发(Concurrent)

一个 CPU 核心,同一时间只能做一件事 快速切换任务:吃饭→看书→吃饭→看书看起来同时在做,实际同一时刻不是同时

特点:交替、快速切换、伪同时、单核可用

  1. 并行(Parallel)

多个 CPU 核心,同一时刻真正一起做事一个核心吃饭,一个核心看书真正同时进行

特点:同时、一起执行、真同时、必须多核

二、对比表格

对比维度 并发 Concurrent 并行 Parallel
CPU 数量 单核 / 多核都可以 必须多核
同一时刻状态 只能执行 1 个任务 同时执行多个任务
执行方式 快速交替切换 同时独立运行
本质 逻辑上同时 物理上同时
生活例子 一个人交替洗碗、扫地 两个人同时洗碗、扫地

3.goroutine协调创建

goroutine是Go语言中的轻量级线程实现,有Go运行时(runtime)进行管理,它会智能地将goroutine中的任务合理地分配给每个CPU

(1)普通函数创建 goroutine

go funcName(paramlist)

go:是创建goroutine使用的关键字

funcName:是函数名

paramlist:函数参数

示例代码:

复制代码
package main

import (
	"fmt"
	"time"
)

// 普通函数
func printMessage(msg string) {
	fmt.Println(msg)
}

func main() {
	// 使用普通函数创建goroutine
	go printMessage("Hello from goroutine")

	// 主goroutine继续执行
	fmt.Println("Hello from main")

	// 等待足够时间确保goroutine执行
	time.Sleep(1 * time.Second)
}

(2)使用匿名函数创建 goroutine

go func(paramlist){

执行代码

}(paramlist2)

go:是创建goroutine使用的关键字

func:是创建匿名函数使用的关键字

paramlist:是匿名函数使用的形参

paramlist2:是匿名函数使用的实参

示例代码:

复制代码
package main

import (
	"fmt"
	"time"
)

func main() {
	// 使用匿名函数创建goroutine
	go func(msg string) {
		fmt.Println(msg)
	}("Hello from anonymous goroutine")

	// 主goroutine继续执行
	fmt.Println("Hello from main")

	// 等待足够时间确保goroutine执行
	time.Sleep(1 * time.Second)
}

注意事项

两个示例中都使用了time.Sleep来确保goroutine有足够时间执行。在实际应用中,通常使用更可靠的同步机制如sync.WaitGroup或通道(channel)来协调goroutine的执行。

4.channel通信机制

channel(通道)是Go语言中的一个核心类型,可以把他看成一个管道,并发核心单元通过它可以发送或者接受函数,实现通信功能

(1)声明通道类型

var chanName chan chanType

chanName:表示保存通道的变量,声明后默认为nil,需要通过make()函数创建后才能使用

chanType:表示通道内的数据类型

(2)创建通道(无缓冲通道)

chanName := make(chan chanType)

(3)使用通道发送数据

chanName <- chanValue

chanValue:是变量、常量、表达式、函数返回值等

(4)使用通道阻塞接收数据

data := <-ch

上面的语法执行过程中会出现通道阻塞,知道接收到数据并赋值给变量data

(5)使用通道非阻塞接收数据

data,ok := <-ch

(6)忽略接收到的所以数据

<-ch

上面的语法在执行过程中会出现通道阻塞,直到接收到数据,但接收到的数据会忽略

(7)创建通道(有缓冲)

chanName := make(chan chanType,cacheSize)

在以上的语法中,变量chanName表示通过make()函数创建好的通道实例,参数chanType表示通道发送和接收的数据类型,参数cacheSize表示通道最多可以保存的元素数量

(8)无缓冲通道有缓冲通道的特点和阻塞条件

无缓冲的通道是指在接收信息前没有能力保存任何值的通道。这种类型的通道要求执行发送的goroutine和执行接收的goroutine同时准备好,才能完成发送和接收的操作。因为无缓冲通道的发送和接收行为时同步的,两者任意一个操作都无法离开另一方的操作。因此若两个goroutine没有同时准备好,会导致先执行发送或接收操作的goroutine进入阻塞等待状态

使用无缓冲通道实现同步通信的示例代码

以下代码演示了如何使用无缓冲通道在Go协程之间进行同步通信。无缓冲通道要求发送和接收操作同时准备好才能成功通信,否则会阻塞。

复制代码
package main

import (
    "fmt"
    "time"
)

func worker(done chan bool) {
    fmt.Println("working...")
    time.Sleep(time.Second)
    fmt.Println("done")
    done <- true
}

func main() {
    done := make(chan bool)
    go worker(done)
    <-done
}

有缓冲的通道是一个有限大小的存储空间形成的带有缓冲的通道,信息被接收前能存储一个或多个值,不强制要求goroutine之间必须同时完成发送和接收操作。因此只有在通道中没有要接收的值时,接收操作才会阻塞;只有在通道没有可用缓冲区容纳被发送的值时,发送动作才会阻塞

使用缓冲通道实现异步通信示例代码

缓冲通道允许在通道容量未满时不阻塞发送操作。这段代码展示了缓冲通道的用法

复制代码
package main

import "fmt"

func main() {
    messages := make(chan string, 2)
    messages <- "buffered"
    messages <- "channel"
    fmt.Println(<-messages)
    fmt.Println(<-messages)
}
相关推荐
xxyy8882 小时前
关于labelimg安装后在标注过程中闪退和死机的问题处理
开发语言·python
JAVA面经实录9172 小时前
Java开发工程基础完整手册(企业实战完整版)
java·开发语言·git·ci/cd·svn·github·intellij idea
skywalk81633 小时前
【文言心】- 中文编程语言> 一门追求同像性(Homoiconicity)的中文编程语言,代码即数据,数据即代码。
开发语言
南境十里·墨染春水3 小时前
C++笔记 forward完美转发
开发语言·c++·笔记
代码羊羊3 小时前
Rust 格式化输出完全攻略:从入门到精通
开发语言·后端·rust
不会编程的懒洋洋3 小时前
WPF XAML+布局+控件
xml·开发语言·c#·视觉检测·wpf·机器视觉·视图
Rust研习社3 小时前
Rust + PostgreSQL 极简技术栈应用开发
开发语言·数据库·后端·http·postgresql·rust
雾岛听风6913 小时前
JavaScript基础语法速查手册
开发语言·前端·javascript
c++之路3 小时前
C++ STL
java·开发语言·c++