Golang并发(二) - Goroutine

What you are wasting today is tomorrow for those who died yesterday; what you hate now is the future you can not go back.

你所浪费的今天是昨天死去的人奢望的明天; 你所厌恶的现在是未来的你回不去的曾经。

什么是goroutine

    goroutines是与其他函数或方法同时运行的函数或方法。

    goroutines可以被认为是轻量级的线程。与线程相比,创建goroutine的成本很小。因此它的应用程序通常有数千个并发运行的goroutines。

goroutines优于线程的优势

    与线程相比,goroutine开销很小。它们的堆栈大小只有几kb,并且堆栈可根据应用程序的需要增长和缩小,而线程,堆栈大小必须指定并固定。

    goroutine被多路复用到更少数量的os线程。在一个有数千个例程的程序中可能只有一个线程。如果该线程中的任何goroutine阻止了并等待用户输入,则会创建另一个os线程,并将其余的goroutine移至新的os线程。所有这些都受到运行时的影响,我们作为程序员从这些复杂的细节中抽象出来,并得到一个干净的api来处理并发。

    goroutines使用channel进行通信。channel的设计可防止使用goroutine访问共享内存时发生资源竞争。channel可以被认为是一个与某个goroutine通信的管道。

如何开启一个groutine

    使用关键字go前缀函数或方法调用,因此将会产生一个并发运行的新goroutine。

实例解析:

package main

import (  
    "fmt"
)

func hello() {  
    fmt.Println("Hello world goroutine")
}
func main() {  
    go hello()
    fmt.Println("main function")
}

输出: main function

注意: 此时的go hello()会开启一个新的协程,并与main的主线程并行运行。但是程序在调用go hello()后会立即返回,继续往下main的执行,忽略goroutine的输出,那么main程并不会等待新协程的结束而直接退出.

如果主程序终止,那么程序将被终止,并且其他所有goroutine将会终止执行。

启动多个goroutine

让我们编写一个启动多个goroutine的程序,以更好地理解goroutine。

ackage main

import (  
    "fmt"
    "time"
)

func numbers() {  
    for i := 1; i <= 5; i++ {
        time.Sleep(250 * time.Millisecond)
        fmt.Printf("%d ", i)
    }
}
func alphabets() {  
    for i := 'a'; i <= 'e'; i++ {
        time.Sleep(400 * time.Millisecond)
        fmt.Printf("%c ", i)
    }
}
func main() {  
    go numbers()
    go alphabets()
    time.Sleep(3000 * time.Millisecond)
    fmt.Println("main terminated")
}

疑惑:

    你可能会疑惑, 如果第一个goroutine创建之后, 其中的有sleep那么导致第二个goroutine的堵塞或者等待创建中, 当第一个goroutine输出完成,再来执行第二个goroutine的创建和执行。

解答:

    上面我们说过, 主进程main在执行到go FUNC()时, 执行简单的调用后立刻返回,并不关心新goroutine中的Code所执行的任何输出。所以main会顺序执行code语句。

最上面的两个goroutine是并行执行的。

这就是关于channel简单的介绍。

猜你喜欢

转载自my.oschina.net/90design/blog/1634115