您现在的位置是:首页 >技术杂谈 >GO语言小锤硬磕.二十一 协程与锁网站首页技术杂谈

GO语言小锤硬磕.二十一 协程与锁

shockWaveGo 2023-05-14 20:00:02
简介GO语言小锤硬磕.二十一 协程与锁

我们先弄懂几个名词

运行方式:

        1.串行  按顺序执行。同一时刻只允许有一条指令在CPU上执行。

        2.并行  一起执行。同一时刻允许多条指令在多个CPU上执行。

并发:是伪并行,是有选择的串行。

        同一时间只能有一条指令在CPU上执行。但CPU会快速的在多条指令之间轮询执行。

程序:是一个可以实现特定功能的指令集。

进程:是程序在操作系统中的一次执行过程,是系统进行资源分配调度的基本单位。

        例如你打开记事本程序,就建立了一个进程。再次启动又会创建一个

线程:是进程中的一个执行实例,是程序执行的最小单元。

一个进程中至少有一个线程,我们称为主线程。一个进程中除主线程,我们还可以创建销毁多个线程。这些线程可以实现特定的功能。

协程:协程是一种用户态的轻量级线程。又称微线程。英文名Goroutine

一个线程中可以有任意多额协程,但在某一刻只能有一个协程在运行,多个协程分享所在线程分配到的计算机资源。

在协程中,调用一个任务就像调用一个函数一样,消耗极少的资源,但能达到进程、线程相同的并发效果。

package main
import(
    "fmt"
    "time"
)
func sing(){
    for i:=0;i<10;i++{
        fmt.Println("我在吹口哨")
        time.Sleep(time.Millisecond)
    }
}
func dance(){
    for i:=0;i<10;i++{
        fmt.Println("我在跳舞")
        time.Sleep(time.Millisencond)
    }
}
func main(){
    //串行,吹完口哨,再跳舞
    sing()
    dance()

    //并行。接着奏乐接着舞
    go sing()    //开启了一个协程
    go dance()   //又开启一个协程
    
    for{        //主线程结束,程序会退出。所以这里使用死循环。
        ;
    }
    
}

runtime包中常用的函数

Gosched()使当前go程放弃处理器,以让其他go程运行

package main
import(
    "fmt"
    "runtime"
)
func sing(){
    for i:=0;i<10;i++{
        fmt.Println("我在吹口哨")
        runtime.Gosched() //放弃处理器,让其他go程运行,不会挂起当前go程,未来会恢复
    }
}

func dance(){
    for i:=0;i<10;i++{
        fmt.Println("我在跳舞")
        runtime.Gosched()
    }
}

func main(){
    //一边奏乐一边舞,吹一下口哨,跳一下舞。
    go singg()
    go dance()
    for{
        ;
    }
}

Goexit()终止调用它的go程,其他go程不受影响

package main
import(
    "fmt"
    "runtime"
)

func main(){

    go func(){
        fmt.Println("123")
        //return             退出当前函数
        //runtime.Goexit()   退出当前协程
        test()
        fmt.Println("456")
    }()

    for{
    ;
    }
}

func test(){
    fmt.Println("abc")
    //return 只会结束当前函数,协程中的其他的代码会继续执行
    runtime.Goexit()    //会结束整个协程,协程中之后的代码都不会执行
    fmt.Println("def")

}

NumCPU与GOMAXPROCS设置可以同时执行额最大CPU数,并返回先前的设置

package main
import(
    "fmt"
    "runtime"
)
func main(){
    num:=runtime.NumCPU();
    fmt.Println(num)
    runtime.GOMAXPROCS(num)
}

多线程的同步问题

互斥锁

        互斥锁的本质是一个goroutine访问的时候,其他goroutine不能访问

这样就实现资源同步,但是避免资源竞争的同时也降低了程序的并发性能,程序由原来的并发执行变成了串行。

package main
import(
    "fmt"
    "sync"
    "time"
)
//创建一把互斥锁
var lock sync.Mutex

func printer(str string) {
    //拿到执行上锁
    lock.Lock()
    for_,v := range str{
        fmt.Printf("%c",v)
        time.sleep(time.Millisecond*500)
    }
    lock.Unlock()
    
}

func personl(){
    printer("hello")
}
func person2(){
    printer("world")
}

func main(){
    go person1()
    go person2()
    for{
        ;
    }
}

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。