golang学习笔记11——Go 语言的并发与同步实现详解

文章目录

引言

在现代软件开发中,并发和同步是非常重要的概念。Go 语言以其简洁高效的并发模型而备受关注。本文将详细介绍 Go 语言中并发与同步的实现方式,并结合代码示例进行深入讲解。

Go 语言的并发模型

1.goroutine

  • Goroutine 是 Go 语言中实现并发的轻量级线程。与传统的线程相比,goroutine 占用的内存更少,创建和切换的开销也更小。
  • 创建 goroutine 非常简单,只需要在函数调用前加上 go 关键字即可。例如:
golang 复制代码
package main

import (
    "fmt"
    "time"
)

func printNumbers() {
    for i := 1; i <= 5; i++ {
        fmt.Println(i)
        time.Sleep(time.Millisecond * 500)
    }
}

func main() {
    go printNumbers()
    fmt.Println("Main function")
    time.Sleep(time.Second * 2)
}

在上面的代码中,printNumbers 函数会在一个新的 goroutine 中执行,而 main 函数会继续执行。这样就实现了并发执行两个任务。

2.channel

  • channel 是用于 goroutine 之间通信的机制。它可以在不同的 goroutine 之间传递数据,实现同步和协调。
  • 创建 channel 可以使用 make 函数。例如:ch := make(chan int) 创建了一个整数类型的 channel。
  • 可以使用 <- 操作符从 channel 中接收数据或向 channel 中发送数据。例如:
golang 复制代码
package main

import (
    "fmt"
)

func sendData(ch chan int) {
    for i := 1; i <= 5; i++ {
        ch <- i
    }
    close(ch)
}

func main() {
    ch := make(chan int)
    go sendData(ch)
    for num := range ch {
        fmt.Println(num)
    }
}

在上面的代码中,sendData 函数会向 channel 中发送数据,而 main 函数会从 channel 中接收数据。当 sendData 函数发送完所有数据后,会关闭 channel。main 函数中的 for range 循环会自动检测 channel 的关闭,并退出循环。

Go 语言的同步机制

1.mutex

  • mutex(互斥锁)是一种用于保护共享资源的同步机制。在 Go 语言中,可以使用 sync.Mutex 类型来实现互斥锁。
  • 使用互斥锁的步骤如下:
    • 创建一个 sync.Mutex 类型的变量。
    • 在需要保护的代码块前,调用 Lock 方法获取锁。
    • 在代码块执行完毕后,调用 Unlock 方法释放锁。
  • 例如:
golang 复制代码
package main

import (
    "fmt"
    "sync"
)

var counter int
var mutex sync.Mutex

func increment() {
    mutex.Lock()
    defer mutex.Unlock()
    counter++
    fmt.Println(counter)
}

func main() {
    for i := 0; i < 5; i++ {
        go increment()
    }
    // 等待所有 goroutine 执行完毕
    time.Sleep(time.Second)
}

在上面的代码中,increment 函数会对共享变量 counter 进行加一操作。为了避免多个 goroutine 同时访问和修改 counter 变量,使用了互斥锁 mutex。在 increment 函数中,首先调用 Lock 方法获取锁,然后对 counter 进行加一操作,最后调用 Unlock 方法释放锁。

2.wait group

  • WaitGroup 是一种用于等待一组 goroutine 执行完毕的同步机制。在 Go 语言中,可以使用 sync.WaitGroup 类型来实现 WaitGroup。
  • 使用 WaitGroup 的步骤如下:
    • 创建一个 sync.WaitGroup 类型的变量。
    • 在每个需要等待的 goroutine 中,调用 Add 方法增加等待的 goroutine 数量。
    • 在 goroutine 执行完毕后,调用 Done 方法减少等待的 goroutine 数量。
    • 在主 goroutine 中,调用 Wait 方法等待所有 goroutine 执行完毕。
  • 例如:
golang 复制代码
package main

import (
    "fmt"
    "sync"
)

func process(wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Println("Processing...")
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go process(&wg)
    }
    wg.Wait()
    fmt.Println("All processes completed.")
}

在上面的代码中,process 函数会模拟一个处理过程。在主 goroutine 中,创建了一个 sync.WaitGroup 类型的变量 wg。然后,在循环中启动了 5 个 goroutine,并在每个 goroutine 中调用 Add 方法增加等待的 goroutine 数量。在每个 goroutine 执行完毕后,会调用 Done 方法减少等待的 goroutine 数量。最后,在主 goroutine 中,调用 Wait 方法等待所有 goroutine 执行完毕。

总结

Go 语言的并发与同步机制使得开发者能够轻松地编写高效的并发程序。通过 goroutine 和 channel,开发者可以实现轻量级的并发编程,提高程序的性能和响应速度。同时,通过 mutex 和 wait group 等同步机制,开发者可以保护共享资源,确保程序的正确性。在实际开发中,开发者可以根据具体的需求选择合适的并发和同步机制,以实现高效、可靠的程序。

关注我看更多有意思的文章哦!👉👉

相关推荐
其实防守也摸鱼15 分钟前
CTF密码学综合教学指南--第四章
网络·笔记·安全·网络安全·密码学·ctf
nashane15 分钟前
HarmonyOS 6学习:应用签名文件丢失处理与更新完全指南
学习·华为·harmonyos·harmonyos 5
@codercjw18 分钟前
公差的具体标注方法(书本上/理论上标注方法)
学习
久菜盒子工作室1 小时前
时寒冰:第五次产业大转移与未来30年国运:在“双向挤压”中实现惊险一跃
人工智能·学习
05候补工程师2 小时前
【ROS 2 具身智能】Gazebo 仿真避坑指南:从“幽灵机器人”到传感器数据流打通
人工智能·经验分享·笔记·ubuntu·机器人
chushiyunen2 小时前
pandas使用笔记、数据清洗、json_normalize
笔记·pandas
HERR_QQ2 小时前
端到端课程自用 4 规划 基于自规划AR的端到端规划 AI 笔记
人工智能·笔记·自动驾驶·transformer
Amazing_Cacao2 小时前
CFCA精品可可产区认证课程风土解析(美洲):打破风味堆叠的假象,建立时间轴上的层次展开阅读系统
学习
永远不会的CC3 小时前
浙江华昱欣实习(4月23日~ 4月19日)
后端·学习
二哈赛车手3 小时前
新人笔记---实现简易版的rag的bm25检索(利用ES),以及RAG上传时的ES与向量数据库双写
java·数据库·笔记·spring·elasticsearch·ai