在使用多个 goroutine 打印内容时,channel使用的不恰当而导致主线程未等待其它 goroutine 全部执行完毕而退出,造成打印内容不全的问题

package main 
import ( 
    "fmt"
    "runtime"
) 
// 从 1 至 1 亿循环叠加,并打印结果。 
func print(c chan bool, n int) { 
    x := 0 
    for i := 1; i <= 100000000; i++ { 
        x += i 
    } 
    fmt.Println(n, x) 
    if n == 9 { // 当程序运行到第10个goroutine时,给channel添加值,解除阻塞
        c <- true
    } 
} 
  
func main() { 
    // 使用多核运行程序 ,不使用多核时可以正常打印,runtime.NumCPU() 获取cpu个数
    runtime.GOMAXPROCS(runtime.NumCPU()) //使用时,不能打印所有chan,显示结果不是顺序的
    c := make(chan bool) 
    for i := 0; i < 10; i++ { 
        go print(c, i) 
    } 
    <-c // 取channel值,无值时,程序阻塞
    fmt.Println("DONE.") 
}

解决方案一:利用 chan 的缓存机制

package main 
import ( 
    "fmt"
    "runtime"
) 
// 从 1 至 1 亿循环叠加,并打印结果。 
func print(c chan bool, n int) { 
    x := 0 
    for i := 1; i <= 100000000; i++ { 
        x += i 
    } 
    fmt.Println(n, x) 
    c <- true
} 
  
func main() { 
    // 使用多核运行程序 
    runtime.GOMAXPROCS(runtime.NumCPU()) 
    c := make(chan bool, 10) // 有缓冲的channel
    for i := 0; i < 10; i++ { 
        go print(c, i) 
    } 
    for i := 0; i < 10; i++ { 
        <-c 
    } 
    fmt.Println("DONE.") 
}

解决方案二:使用 sync 包的 WaitGroup

package main 
import ( 
    "fmt"
    "runtime"
    "sync"
) 
// 从 1 至 1 亿循环叠加,并打印结果。 
func print(wg *sync.WaitGroup, n int) { 
    x := 0 
    for i := 1; i <= 100000000; i++ { 
        x += i 
    } 
    fmt.Println(n, x) 
    // 标识一次任务完成 
    wg.Done() 
} 
  
func main() { 
    // 使用多核运行程序 
    runtime.GOMAXPROCS(runtime.NumCPU()) 
    // 创建等待组 
    wg := sync.WaitGroup{} 
    // 设置需要等待的对象个数 
    wg.Add(10) 
    for i := 0; i < 10; i++ { 
        go print(&wg, i) 
    } 
    // 等待所有任务完成 
    wg.Wait() 
    fmt.Println("DONE.") 
}

 

posted on 2015-03-20 17:31  浊浊然  阅读(849)  评论(0)    收藏  举报