Golang的并发与goroutine

1、并发的含义
并发与并行的区别:
并发:逻辑上具备同时处理多任务的能力(由程序的逻辑实现决定)
并行:物理上在同一时刻执行多个并发任务(由的处理器核数决定)

实际的单核处理器在处理任务的时候基本都是以间隔方式切换执行(时间片调度),并行是并发程序在设计的理想执行模式。

任务可以并行执行其中多线程和多进程是基本条件。
然而在单线程中引入了一个比线程还轻量级的运行单元,协程(coroutine)实现并发。
如果处理器为单核单线程,虽然一次只可以处理一个任务,但是并发的程序设计(使用协程)不但可以减少多线程带来的资源开销,也可以减少阻塞的时间占比,提高执行效率
(协程在内部执行时是串行,并且可以控制调度(程序内部实现),不需要进行同步处理,提高了并发安全)
实现并发的三种程序实现方式:
多进程:主要用于分布式,负载均衡,减轻单进程垃圾回收压力(开销大,程序健壮,切换麻烦)
多线程:抢占更多的cpu资源,(开销相对较小,并发量大于进程)
多协程:提高cpu时间片利用率(开销更小,并发量更大)
更多的时候程序是使用这三种方式组合的方式实现的。
【Golang的并发与goroutine】2、Golang中的goroutine
Goroutine类似于coroutine但是又区别于coroutine,因为在go语言中在执行一个程序时会先创建多个线程用于执行并发任务,并且又在多线程的基础上进行多goroutine的并发设计,用于提高程序的执行效率
goroutine更像线程和协程的结合体
golang中在函数的调用前加上关键字go即可创建并发任务,新建的任务会被添加到任务队列中而不是立即去执行,当前流程不会被阻塞。
在程序中每个任务单元除了会保存函数指针,调用参数外,系统都会分配栈内存空间。系统默认以MB为单位,goroutine自定义的初始栈仅为2kb,因此golang有利于千万的并发。
在golang中goroutine,sync.WaitGroup,runtime.GOMAXPROCS的联合使用
package mainimport ( "fmt" "math" "runtime" "sync" )func count(){ x := 0; for i:=0; i

与线程不同的是goroutine创建的任务单元无法设置优先级,并且无法获取编号,没有局部存储(TLS),甚至连返回值有时也会被抛弃。这些功能除了优先级,其他都可实现
package mainimport ( "fmt" "sync" )func main(){ var wg sync.WaitGroup var gs [5]struct{//用于实现TLS功能 id int//编号 result int//返回值 } for i:=0; i

3、Gosched和Goexit
gosched主动让出时间片,让出时间片的时长为10ms
package main
import ( "fmt" "runtime" )func main(){ runtime.GOMAXPROCS(1) exit := make(chan struct{}) go func (){//任务c println("c") }() go func() {//任务a defer close(exit) go func(){//任务b fmt.Println("cd") runtime.Gosched() fmt.Println("ab") }() for i := 0; i < 4; i++{ println("a:",i) if i == 1 { runtime.Gosched()//让出时间片 } } }() <-exit } //a: 0 //a: 1 //cd //c //a: 2 //a: 3

goexit终止当前任务,不会影响其他并发任务,不会引发panic,不会被捕获
package mainimport "runtime"func main(){ exit := make(chan struct{}) go func(){ defer close(exit) defer println("a") func(){ defer func() { println("b",recover() == nil)//执行,recover返回nil }() func(){ println("c") runtime.Goexit()//停止整个堆栈调用 println("c done")//以下不会执行 }() println("b done") }() println("a done") }() go func() { println("ddddd") }() <-exit println("main exit") } //c //b true //a //main exit //dddddpackage main import ( "fmt" "runtime" "time" ) func teste(){ fmt.Println("bb") runtime.Goexit() fmt.Println("dd")//不会执行 } func main(){ fmt.Println("aa") go teste() time.Sleep(10*time.Second) fmt.Println("cc")//会执行 }package mainimport ( "fmt" "runtime" ) func teste(){ fmt.Println("bb") //runtime.Goexit() fmt.Println("dd")//不会执行 } func main(){ fmt.Println("aa") go teste() runtime.Goexit()//会等待其他任务结束,然后进程崩溃 fmt.Println("cc") } //aa //bb //dd //fatal error: no goroutines (main called runtime.Goexit) - deadlock!

    推荐阅读