Go 协程

Go 协程

协程与传统的系统级线程和进程相比,协程的优势在于其"轻量级",可以轻松创建上百万个协程而不会导致系统资源衰竭,所以协程也叫做轻量级线程。

在Go中goroutine就是协程的意思,不同的是,Go在runtime、系统调用等多方面对goroutine调度进行了封装和处理,当遇到长时间执行或者进行系统调用时,会主动把当前goroutine的CPU转让出去,让其他goroutine能被调度并执行。

在Go中应用协程

在Go中应用协程,只需要在一个函数调用前加入go关键字,就可以实现协程,如:

package main
import "fmt"
func Add(x,y int){
    z := x + y
    fmt.Println(z)
}

func main(){
    for i:=0;i<10;i++{
        go Add(i, i)
    }
}

运行程序会发现没有任何输出,因为程序运行主函数很快就退出了,没有机会去执行Add函数中输出语句,所以我们在主函数中加一点延时

package main
import (
	"fmt"
	"time"
)
func Add(x,y int){
    z := x + y
    fmt.Println(z)
}

func main(){
    for i:=0;i<10;i++{
        go Add(i, i)
    }
    time.Sleep(time.Second)
}

这里我们就可以看到输出了

4
0
12
6
8
10
16
14
18
2

协程同步

下面的例子使用锁来实现协程同步,但是Go提供了更好的方式实现协程同步。

没有加锁的案例:

func Show(str string){
    for _, i := range str{
        fmt.Printf("%c", i)
        time.Sleep(time.Second)
    } 
}

func main(){
    go Show("hello")
    go Show("world")
    
    // 死循环不让主函数退出,和Sleep效果一致
    for {
        fmt.Print()
    }
}

输出结果:

hwoelrlldo

这并不是我们想要的效果,所以加上锁,案例:

func Show(str string, lock *sync.Mutex){
    lock.Lock()
    for _, i := range str{
        fmt.Printf("%c", i)
        time.Sleep(time.Second)
    } 
    lock.Unlock()
}

func main(){
    lock := &sync.Mutex{}
    go Show("hello", lock)
    go Show("world", lock)
    
    // 死循环不让主函数退出,和Sleep效果一致
    for {
        fmt.Print()
    }
}

加上锁之后,输出的结果:

helloworld

这就达到了协程同步的效果。当然还有更好的方式,channel。

posted @ 2019-08-13 20:25  Yven  阅读(220)  评论(0编辑  收藏  举报