美文网首页
Go语言并发编程—goroutine

Go语言并发编程—goroutine

作者: 蓓蓓的万能男友 | 来源:发表于2018-12-21 11:34 被阅读16次

1 goroutine是什么
goroutine是Go并行设计的核心。goroutine说到底其实就是协程,但是它比线程更小,十几个goroutine可能体现在底层就是五六个线程,Go语言内部帮你实现了这些goroutine之间的内存共享。执行goroutine只需极少的栈内存(大概是4~5KB),当然会根据相应的数据伸缩。也正因为如此,可同时运行成千上万个并发任务。goroutine比thread更易用、更高效、更轻便。

2 创建goroutine
只需在函数调⽤语句前添加 go 关键字,就可创建并发执⾏单元。开发⼈员无需了解任何执⾏细节,调度器会自动将其安排到合适的系统线程上执行。

在并发编程里,我们通常想讲一个过程切分成几块,然后让每个goroutine各自负责一块工作。当一个程序启动时,其主函数即在一个单独的goroutine中运行,我们叫它main goroutine。新的goroutine会用go语句来创建。

示例代码:

package main

import (
    "fmt"
    "time"
)

func newTask() {
    i := 0
    for {
        i++
        fmt.Printf("new goroutine: i = %d\n", i)
        time.Sleep(1 * time.Second) //延时1s
    }
}

func main() {
    //创建一个 goroutine,启动另外一个任务
    go newTask()

    i := 0
    //main goroutine 循环打印
    for {
        i++
        fmt.Printf("main goroutine: i = %d\n", i)
        time.Sleep(1 * time.Second) //延时1s
    }
}

程序运行结果:


image.png

3 主goroutine先退出
主goroutine退出后,其它的工作goroutine也会自动退出:

func newTask() {
    i := 0
    for {
        i++
        fmt.Printf("new goroutine: i = %d\n", i)
        time.Sleep(1 * time.Second) //延时1s
    }
}

func main() {
    //创建一个 goroutine,启动另外一个任务
    go newTask()

    fmt.Println("main goroutine exit")
}

程序运行结果:


image.png

4 runtime包
4.1 Gosched
runtime.Gosched() 用于让出CPU时间片,让出当前goroutine的执行权限,调度器安排其他等待的任务运行,并在下次某个时候从该位置恢复执行。

这就像跑接力赛,A跑了一会碰到代码runtime.Gosched() 就把接力棒交给B了,A歇着了,B继续跑。

示例代码:

func main() {
    //创建一个goroutine
    go func(s string) {
        for i := 0; i < 2; i++ {
            fmt.Println(s)
        }
    }("world")

    for i := 0; i < 2; i++ {
       runtime.Gosched() //import "runtime"
        /*
            屏蔽runtime.Gosched()运行结果如下:
                hello
                hello

            没有runtime.Gosched()运行结果如下:
                world
                world
                hello
                hello
        */
        fmt.Println("hello")
    }
}

4.2 Goexit
调用 runtime.Goexit() 将立即终止当前 goroutine 执⾏,调度器确保所有已注册 defer 延迟调用被执行。

示例代码:

func main() {
    go func() {
        defer fmt.Println("A.defer")

        func() {
            defer fmt.Println("B.defer")
            runtime.Goexit() // 终止当前 goroutine, import "runtime"
            fmt.Println("B") // 不会执行
        }()

        fmt.Println("A") // 不会执行
    }() //别忘了()

    //死循环,目的不让主goroutine结束
    for {
    }
}

程序运行结果:


image.png

4.3 GOMAXPROCS
调用 runtime.GOMAXPROCS() 用来设置可以并行计算的CPU核数的最大值,并返回之前的值。

示例代码:

func main() {
    //n := runtime.GOMAXPROCS(1) //打印结果:                        
111111111111111111110000000000000000000011111...
    n := runtime.GOMAXPROCS(2)     //打印结果:    
010101010101010101011001100101011010010100110...
    fmt.Printf("n = %d\n", n)

    for {
        go fmt.Print(0)
        fmt.Print(1)
    }
}

在第一次执行(runtime.GOMAXPROCS(1))时,最多同时只能有一个goroutine被执行。所以
会打印很多1。过了一段时间后,GO调度器会将其置为休眠,并唤醒另一个goroutine,这时候就开始打印很多0了,在打印的时候,goroutine是被调度到操作系统线程上的。

在第二次执行(runtime.GOMAXPROCS(2))时,我们使用了两个CPU,所以两个goroutine可以一起被执行,以同样的频率交替打印0和1。

相关文章

  • Go的栈空间管理

    栈空间管理的基本逻辑 go语言通过goroutine提供了并发编程支持,goroutine是go运行库的功能,而不...

  • 跟我一起学习GO语言008

    本节我们来看GO语言中的并发。 我们看并发,就不得不学习goroutine,goroutine是Go语言...

  • Go语言并发

    Go语言并发 Go语言级别支持协程,叫做goroutine Go 语言从语言层面支持并发和并行的开发操作 Go并发...

  • 1.2.7go并发编程

    Go语言引入了goroutine概念,它使得并发编程变得非常简单。通过使用goroutine而不是裸用 操作系统的...

  • 一文读懂 Go sync.Cond 设计

    Go 语言通过 go 关键字开启 goroutine 让开发者可以轻松地实现并发编程,而并发程序的有效运行,往往离...

  • Go语言并发编程—goroutine

    1 goroutine是什么goroutine是Go并行设计的核心。goroutine说到底其实就是协程,但是它比...

  • goroutine理解和go内存模型

    原文链接 1. Go goroutine理解 Go语言最大的特色就是从语言层面支持并发(Goroutine),G...

  • Goroutine 是如何运行的

    在 Go 语言中,没有线程,只有 goroutine,这也是 Go 语言原生支持高并发的关键。 goroutine...

  • 第十篇:并发编程

    Go语言区别于其它语言最核心的优势就是:Go对并发编程的大力支持。 一来Go是通过协程goroutine作为执行体...

  • GO 同步原语与锁

    Go 语言作为一个原生支持用户态进程(Goroutine)的语言,当提到并发编程、多线程编程时,往往都离不开锁这一...

网友评论

      本文标题:Go语言并发编程—goroutine

      本文链接:https://www.haomeiwen.com/subject/zrlmkqtx.html