golang 协程 互相通讯

发布时间:2024-07-05 00:35:55

协程是Go语言中提供的一种轻量级的线程管理机制,它能够让我们在程序中创建并发执行的任务。与传统的线程不同,协程具有高效的切换操作和更小的内存占用,在并发编程中得到了广泛的应用。本文将重点介绍协程之间的通讯机制。

Channel - 通讯的基石

在Go语言中,协程之间的通讯主要依靠Channel来实现。Channel是一种特殊的类型,可以被用来在协程之间传递数据。通过Channel,协程可以安全地发送和接收数据,实现高效的同步和通讯。

在使用Channel时,我们需要先创建一个Channel对象,并指定所要传递的数据类型。例如:

ch := make(chan int)

上述代码创建了一个传递整数类型的Channel。一个Channel既可以用于发送数据,也可以用于接收数据。发送数据使用<-运算符,接收数据使用>-运算符。发送方会持续尝试将数据发送到Channel中,直到有接收方准备好接收数据。如果接收方没有准备好,发送方将会被阻塞。反之,如果接收方准备好了但没有数据可以接收,接收方也会被阻塞。

Select - 多路复用通道

在协程的通讯中,有时候我们需要实现对多个Channel同时进行操作,这个时候我们可以使用Select语句。Select语句能够同时等待多个不同的Channel,直到其中一个Channel准备好进行数据传输。

下面是一个使用Select语句的示例:

select {
case value := <-ch1:
    // 处理从ch1接收到的数据
case <-ch2:
    // 只执行一次
case ch3 <- data:
    // 向ch3发送数据
default:
    // 如果没有任何Channel准备好,则执行默认操作
}

上述代码中,Select语句会等待ch1、ch2和ch3三个Channel中的任何一个准备好进行数据传输。如果ch1准备好了,则执行第一个case分支。如果ch2准备好了,则执行第二个case分支。如果ch3准备好了,则向ch3发送数据。如果没有任何Channel准备好,则执行default分支。

Sync - 同步协程

在并发编程中,我们经常需要确保某些操作在协程结束之前完成。为了实现这样的需求,Go语言提供了Sync包,其中的WaitGroup和Mutex类型可以帮助我们实现协程的同步。

WaitGroup类型用于等待一组协程的结束。代码示例如下:

var wg sync.WaitGroup

wg.Add(2)  // 添加两个协程

go func() {
    defer wg.Done()
    // 协程A的逻辑
}()

go func() {
    defer wg.Done()
    // 协程B的逻辑
}()

wg.Wait()  // 阻塞,直到所有协程执行结束

上述代码中,通过调用Add方法将需要等待的协程数量设置为2。然后,分别运行协程A和协程B的逻辑,并在每个协程结束时调用Done方法。最后,使用Wait方法来等待所有的协程执行结束。

Mutex类型是一种互斥锁,用于保护共享资源的访问。示例如下:

var mutex sync.Mutex
var count int

func increment() {
    mutex.Lock()
    count++
    mutex.Unlock()
}

func main() {
    for i := 0; i < 100; i++ {
        go increment()
    }

    time.Sleep(time.Second)
    fmt.Println("Count:", count)
}

在上面的代码中,increment函数使用互斥锁保护了对count变量的访问。在main函数中,通过启动100个协程并发地调用increment函数,最终打印出的count的值应该为100。

通过使用WaitGroup和Mutex,我们可以实现更精细化的协程同步和资源管理。

相关推荐