Go 并发


Go 并发

Go是一种支持并发编程的语言。它使用了一种称为“轻量级线程”(goroutine)的概念,这些线程可以在单个进程内并发运行。

Goroutine

Goroutine是Go语言中的一种并发执行机制,它类似于线程,但是比线程更轻量级,开销更小。在Go中,我们可以创建很多个goroutine,它们可以并行执行,并互不影响。

Goroutine可以通过关键字go来创建:

go function_name()

当我们在程序中使用关键字go创建goroutine时,它会立刻启动一个新的goroutine来执行相应的函数。注意,创建goroutine是异步的,即主程序不会等待goroutine执行完毕才继续执行。

Channel

在Go语言中,goroutine之间的通信可以通过channel来实现。Channel是一种数据类型,可以在goroutine之间传递数据。

创建一个channel:

var ch chan int    // ch是一个int类型的channel

向channel发送数据:

ch <- 123    // 向ch中发送123

从channel接收数据:

x := <- ch    // 从ch中接收数据,并将其赋值给x

当向一个channel发送数据时,如果没有别的goroutine在从这个channel中接收数据,那么发送方会被阻塞,直到有其他的goroutine从这个channel中接收数据。同理,当从一个channel中接收数据时,如果没有别的goroutine在向这个channel中发送数据,那么接收方会被阻塞,直到有其他的goroutine向这个channel中发送数据。

Select

Select语句用于从多个channel中接收数据。它类似于switch语句,但是用于多路复用IO操作。

以下是Select语句的一般形式:

select {
case <-channel1:
    // 从channel1接收到数据时执行的代码
case data := <-channel2:
    // 从channel2接收到数据时执行的代码
default:
    // 默认执行的代码,如果所有的channel都没有数据可接收时就会执行
}

当执行Select语句时,如果有多个channel都可以接收数据,那么会随机选择一个channel进行操作。如果没有任何一个channel可以接收数据,则Select语句会被阻塞,直到有一个channel可以接收数据。

Mutex

Mutex是一种互斥锁,用于保护共享数据的访问。在Go中,我们可以使用sync.Mutex类型的变量来创建一个Mutex对象。

当代码需要访问共享数据时,需要先获取这个Mutex对象的锁,然后访问共享数据。当访问完成后,需要释放这个Mutex对象的锁。

以下是Mutex对象的基本使用方法:

var mutex sync.Mutex    // 创建一个Mutex对象

mutex.Lock()            // 获取锁
// 访问共享数据的代码
mutex.Unlock()          // 释放锁

WaitGroup

WaitGroup用于等待一组goroutine的执行完成。在WaitGroup中,我们可以使用Add()方法增加一个goroutine的计数器,使用Done()方法减少一个goroutine的计数器,使用Wait()方法来等待所有goroutine的计数器归零。

以下是WaitGroup的基本使用方法:

var wg sync.WaitGroup    // 创建一个WaitGroup对象

wg.Add(1)                // 为一个goroutine的计数器 +1

go func() {
    // goroutine的代码
    wg.Done()            // 为一个goroutine的计数器 -1
}()

wg.Wait()                // 等待所有goroutine的计数器归零

Conclusion

Go语言通过Goroutine、Channel、Select、Mutex、WaitGroup等机制支持并发编程。它提供了简单易用的工具和语法来编写并发程序,大大提高了程序的性能和可维护性。