也许你已经猜到了,通道非常适用于对两个goroutine进行同步,当一个goroutine需要依赖另一个goroutine时,更是如此。事不宜迟,让我们马上来看看代码清单9-7所示的程序:这个程序沿用了上一节展示过的例子,唯一的不同在于,这次的程序使用了通道而不是等待组来对goroutine进行同步。

代码清单9-7 使用通道同步goroutine

package main

import (
    "fmt"
    "time"
)

func printNumbers2(w chan bool) {  
    for i := 0; i < 10; i++ {    
        time.Sleep(1 * time.Microsecond)    
        fmt.Printf("%d ", i)  
    }  
    w <- true//把一个布尔值放入通道,以便解除主程序的阻塞状态
}

func printLetters2(w chan bool) {  
    for i := 'A'; i < 'A'+10; i++ {    
        time.Sleep(1 * time.Microsecond)    
        fmt.Printf("%c ", i)
    }
    w <- true//把一个布尔值放入通道,以便解除主程序的阻塞状态
}

func main() {  
    w1, w2 := make(chan bool), make(chan bool)  
    go printNumbers2(w1)  
    go printLetters2(w2)  
    //主程序将一直阻塞,直到通道里面出现可弹出的值为止
    <-w1  
    <-w2
}

先来看看这个程序中的main函数。它首先创建了w1w2这两个bool类型的通道,接着以goroutine方式运行了printNumbers2函数和printLetters2函数,并将两个通道分别传给了这两个函数。在启动两个goroutine之后,main函数将会尝试从通道w1中移除一个值,但由于通道w1当时并没有包含任何值,所以main函数将会在此处阻塞。当printNumbers2即将执行完毕,并将一个true值放入通道w1之后,main函数的阻塞状态才会被解除,并继续尝试从第二个通道w2中弹出一个值。跟之前一样,在printLetters2执行完毕并将true值放入通道w2之前,main函数将一直阻塞,直到它成功取得了w2通道中的true值之后,阻塞才会解除,然后main函数才会顺利退出。

需要注意的是,因为我们只是想要在goroutine执行完毕之后解除对main函数的阻塞,而不是真正地想要使用通道中存储的值,所以程序在从通道w1w2里面取出值之后并没有使用这些值。

代码清单9-7展示的是一个非常简单的例子,这个例子中的程序使用通道只是为了对多个goroutine进行同步,但这些goroutine之间并没有通信。不过在接下来的一节,我们就会看到一个在多个goroutine之间传递消息的例子。

results matching ""

    No results matching ""