【go语言学习】并发实现

2020-10-03  本文已影响0人  Every_dawn

一、什么是goroutine

Goroutine是Go语言特有的名词。区别于进程Process,线程Thread,协程Coroutine,因为Go语言的创造者们觉得和他们是有所区别的,所以专门创造了Goroutine。

Goroutine是与其他函数或方法同时运行的函数或方法。Goroutines可以被认为是轻量级的线程。与线程相比,创建Goroutine的成本很小,它就是一段代码,一个函数入口。以及在堆上为其分配的一个堆栈(初始大小为4K,会随着程序的执行自动增长删除)。因此它非常廉价,Go应用程序可以并发运行数千个Goroutines。

二、主goroutine

封装main函数的goroutine称为主goroutine。
主goroutine所做的事情并不是执行main函数那么简单。它首先要做的是:设定每一个goroutine所能申请的栈空间的最大尺寸。在32位的计算机系统中此最大尺寸为250MB,而在64位的计算机系统中此尺寸为1GB。如果有某个goroutine的栈空间尺寸大于这个限制,那么运行时系统就会引发一个栈溢出(stack overflow)的运行时恐慌。随后,这个go程序的运行也会终止。

此后,主goroutine会进行一系列的初始化工作,涉及的工作内容大致如下:

三、如何使用goroutine

Go语言中使用goroutine非常简单,只需要在调用函数的时候在前面加上go关键字,就可以为一个函数创建一个goroutine。

一个goroutine必定对应一个函数,可以创建多个goroutine去执行相同的函数。

package main

import (
    "fmt"
)

func main() {
    go f1()
    fmt.Println("你好,世界")
}

func f1() {
    fmt.Println("hello world")
}

运行结果

你好,世界

或者

hello world
你好,世界

多次运行以上程序,会出现不同的输出结果。
这是因为:上面的程序有main函数主goroutine,和f1函数子goroutine。程序运行时,当子goroutine优先抢到系统资源,就会输出hello world,然后主goroutine输出你好,世界,结束程序;当主goroutine优先抢到系统资源,就会输出你好,世界,然后主goroutine就结束了,所有在main()函数中启动的goroutine会一同结束。

修改以上代码:

package main

import (
    "fmt"
    "time"
)

func main() {
    go f1()
    fmt.Println("你好,世界")
    time.Sleep(1 * time.Second)
}

func f1() {
    fmt.Println("hello world")
}

运行结果

你好,世界
hello world

增加了主goroutine睡眠1s,这样子goroutine有足够的时间来执行。

四、启动多个goroutine

package main

import (
    "fmt"
    "time"
)

func main() {
    go numbers()
    go alphabets()
    time.Sleep(3000 * time.Millisecond)
    fmt.Println(" main over")
}

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)
    }
}

运行结果

1a23b4c5de main over
上一篇下一篇

猜你喜欢

热点阅读