Goroutine和Channel总结

Golang对并发的支持相对简单,采用的是Goroutine的机制,类似于协程。

采用Go关键字就能实现。

Goroutine 基础

第一种情况

func main() {
    for i := 0; i < 10; i++ {
        go func(i int) {
            fmt.Println(i)

        }(i)
    }
}

猜猜以上代码的输出,结果是什么都不输出。
为什么呢,明明我用go开启了10个并发协程为什么什么都不输出呢?

原因:当走完for循环的时候,main方法就结束了。这个时候 程序就会释放所有资源。所以go创建的并发func并不会执行。

第二种情况

func main() {
    wg := new(sync.WaitGroup)
    wg.Add(10)
    for i := 0; i < 10; i++ {
        go func(i int) {
            defer wg.Done()
            fmt.Println(i)

        }(i)
    }
    wg.Wait()
}

先介绍一下sync.WaitGroup,点开可以看文档。

wg.Add(delta int)方法就是来设定应等待的线程的数量。
wg.Done() Done方法减少WaitGroup计数器的值,应在线程的最后执行。
wg.Wait() Wait方法阻塞直到WaitGroup计数器减为0。

这样写的目的就是让main方法阻塞。
那么输出的话就会很随机,因为你也不知道哪个线程会先跑完。

附加runtime方法

func main() {
    runtime.GOMAXPROCS(2)
    wg := new(sync.WaitGroup)
    wg.Add(10)
    for i := 0; i < 10; i++ {
        go func(i int) {
            defer wg.Done()
            if i == 3 {
                runtime.Goexit()
            }
            fmt.Println(i)

        }(i)
    }
    wg.Wait()
}

GOMAXPROCS 文档
Goexit 文档

runtime.GOMAXPROCS(2) OMAXPROCS设置可同时执行的最大CPU数,来实现多核多线程并行。
runtime.Goexit() Goexit终止调用它的go程。其它go程不会受影响。Goexit会在终止该go程前执行所有defer的函数。

Goroutine通信 --> Channel

Channel的设计为了实现Goruntine直接的通信。值得一提的是Channel是值类型,这点需要注意。

//创建
chan = make(chan int)
使用channel在俩goroutine间传递消息
func main() {
    runtime.GOMAXPROCS(4)
    ch := make(chan int)
    go add(1, 2, ch)
    go printAaddB(ch)
}

func add(a int, b int, ch chan int) {
    ch <- a + b
}

func printAaddB(ch chan int) {
    fmt.Println(<-ch)
}

这样便实现了chennel传递消息。

参考

以上内容如有错误,请指出。

Go 学习笔记 第四版 雨痕
Go 中文文档

你可能感兴趣的:(Goroutine和Channel总结)