全国旗舰校区

不同学习城市 同样授课品质

北京

深圳

上海

广州

郑州

大连

武汉

成都

西安

杭州

青岛

重庆

长沙

哈尔滨

南京

太原

沈阳

合肥

贵阳

济南

下一个校区
就在你家门口
+
当前位置:首页  >  技术干货  >  详情

深入浅出Go中的并发编程技巧

来源:千锋教育
发布人:xqq
2023-12-27

推荐

在线提问>>

深入浅出 Go 中的并发编程技巧

并发编程是 Go 语言的一大优势,在多核 CPU 的情况下,Go 语言可以有效地利用多核资源,提高程序的执行效率。然而并发编程并不是一件简单的事情,需要掌握一些技巧才能写出高效且正确的并发程序。

本文将深入浅出介绍 Go 中的并发编程技巧,包括 goroutine,channel,sync 包等,让你在写并发程序时更加得心应手。

1. goroutine

goroutine 是 Go 中轻量级的线程,可以并发地执行代码块。在 Go 中使用 goroutine 的方式非常简单,只需要在函数或代码块前面加上关键字 go 即可。

例如:

func main() {    go func() {        // 执行一些任务    }()    // 执行其他任务}

在上面的示例中,我们在 main 函数中使用了 go 关键字,启动了一个新的 goroutine 来执行一个匿名函数。这个 goroutine 和 main 函数是并发执行的,即它们彼此独立地执行。

goroutine 的执行方式是异步的,即 goroutine 启动后,会立即返回,并不会等待 goroutine 的代码块执行完毕。因此需要使用一些机制来等待 goroutine 的执行结果,例如 channel。

2. channel

channel 是 Go 中用于多个 goroutine 之间通信的一种机制,它可以实现 goroutine 之间的同步和并发控制。

在 Go 中使用 channel 的方式也非常简单,只需要使用 make 函数创建一个 channel,并使用 <- 操作符向 channel 中发送和接收数据即可。

例如:

func main() {    ch := make(chan int)    go func() {        ch <- 1    }()    // 从 channel 中接收数据    num := <-ch    fmt.Println(num)}

在上面的示例中,我们使用 make 函数创建了一个类型为 int 的 channel,并在一个新的 goroutine 中向 channel 中发送了一个整数 1。然后在 main 函数中使用 <- 操作符从 channel 中接收数据,并将接收到的数据赋值给变量 num。

需要注意的是,当向 channel 中发送数据时,如果 channel 已满,发送操作将会阻塞,直到有一个 goroutine 从 channel 中接收数据;当从 channel 中接收数据时,如果 channel 中没有数据,接收操作将会阻塞,直到有一个 goroutine 向 channel 中发送数据。

因此,可以使用 channel 来控制 goroutine 的执行流程,例如:

func main() {    ch := make(chan int)    go func() {        // 执行一些任务        ch <- 1    }()    // 等待 goroutine 执行完毕    <-ch    // 执行其他任务}

在上面的示例中,我们在执行完 goroutine 中的任务后,向 channel 中发送了一个整数 1。然后在 main 函数中使用 <- 操作符从 channel 中接收数据,这里会阻塞等待 goroutine 的执行结果。当接收到 goroutine 发送的数据后,main 函数会继续执行其他任务。

3. sync 包

sync 包是 Go 中用于实现同步和并发控制的一种机制,它提供了一些原语和工具来协调多个 goroutine 的执行流程。

其中最常用的原语是 Mutex 和 RWMutex。Mutex 是一种互斥锁,用于保护共享资源,保证同一时刻只有一个 goroutine 可以访问共享资源。RWMutex 是一种读写锁,用于保护共享资源,允许多个 goroutine 同时读共享资源,但只允许一个 goroutine 写共享资源。

例如:

import (    "sync")type Counter struct {    value int    mu    sync.Mutex}func (c *Counter) Increment() {    c.mu.Lock()    defer c.mu.Unlock()    c.value++}func (c *Counter) Value() int {    c.mu.Lock()    defer c.mu.Unlock()    return c.value}

在上面的示例中,我们定义了一个 Counter 结构体,并使用 Mutex 来保护 Counter 的 value 字段,保证只有一个 goroutine 可以同时访问 value 字段。

在 Increment 方法中,我们首先使用 Lock 方法获取锁,然后在函数执行完毕后使用 Unlock 方法释放锁。在 Value 方法中也是类似的方式获取和释放锁。

需要注意的是,使用锁会降低程序的并发性能,因此在使用锁时需要注意锁的粒度,尽量减小锁的粒度,避免锁的竞争。

除了 Mutex 和 RWMutex 外,sync 包还提供了一些原语和工具,例如 WaitGroup,Once,Cond 等用于协调多个 goroutine 的执行流程。

4. 总结

本文介绍了 Go 中的并发编程技巧,包括 goroutine,channel,sync 包等。通过掌握这些技巧,可以编写高效且正确的并发程序,充分发挥多核 CPU 的性能。在实际开发中,可以根据具体的需求选择合适的并发编程方式,例如使用 goroutine 和 channel 实现任务并发执行,使用 Mutex 和 RWMutex 保护共享资源等。

相关文章

如何在Go中实现动态数据结构

聊聊Golang中的反射机制

从零开始学习Go语言入门指南

如何使用GoLand进行调试

Goland开发工具使用指南

开班信息 更多>>

课程名称
全部学科
咨询

HTML5大前端

Java分布式开发

Python数据分析

Linux运维+云计算

全栈软件测试

大数据+数据智能

智能物联网+嵌入式

网络安全

全链路UI/UE设计

Unity游戏开发

新媒体短视频直播电商

影视剪辑包装

游戏原画

    在线咨询 免费试学 教程领取