> 文章列表 > GO语言小锤硬磕.二十一 协程与锁

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

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.Mutexfunc 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{;}
}