开发者

Go语言Goroutinue和管道效率详解

目录
  • goroutinue基本介绍
    • 进程和线程说明
    • 并发和并行
    • 同步和异步
  • Go协程和Go主线程
    • go协程特点
  • goroutinue基本使用
    • 实验代码
    • 效果图
    • 执行流程图
  • goroutinue的调度模型
    • MPG
    • MPG运行状态1
    • MPG运行状态2
  • 管道(channel)
    • 不同协程之间如何通讯
    • 全局变量加锁同步缺陷
    • 管道基本介绍
    • 管道基本使用 声明和定义
    • 管道关闭和遍历
      • 关闭
      • 遍历
    • 管道注意事项
    • 综合案例

      goroutinue基本介绍

      进程和线程说明

      • 进程介绍程序在操作系统中的一次执行过程,是系统进行资源分配和调度的基本单位
      • 线程只是进程的一个执行实例或流程,是程序执行的最小单元
      • 一个进程可以有多个线程,但是一个线程只能对应一个进程
      • 同一个进程中的多个线程可以并发执行
      • 程序:运行起来的应用程序就称为进程,也就是当程序不运行的时候我们称为程序,当程序运行起来他就是一个进程,通俗的理解就是不运行的时候是程序,运行起来就是进程。程序只有一个,但是进程有多个

      并发和并行

      • 并发:多个任务依次执行,执行过程中多个任务可以替换执行,在某一个时刻是一个任务在执行php,但是在某个时间段内是多个任务在执行。
      • 并行:多个任务没有顺序,同时执行,最终的执行结果跟耗时最长的任务有关
      • 串行:多个任务依次执行,上一个任务没有完成时不能执行后续的任务,最明显的同步执行过程

      同步和异步

      • 同步:描述的就是串行执行过程,多个任务按照顺序依次执行的过程
      • 异步:描述的就是并发和并行的过程,就是多个任务在一个时间段内同时执行,每个任务都不会等待其他任务执行完成后执行

      Go协程和Go主线程

      Go主线程:一个Go线程上,可以起多个协程,协程是轻量级的线程

      go协程特点

      • 有独立的栈空间
      • 共享程序堆空间
      • 调度由用户控制
      • 协程是轻量级的线程

      goroutinue基本使用

      实验代码

      package main
      import (
      	"fmt"
      	"runtime"
      	"strconv"
      	android"time"
      )
      func main() {
      	//编写一个函数,每隔1s输出"hello,world"
      	//要求主线程和gorutine同时执行
      	go test()
      	//在主线程中,开启一个goroutine,该协程每隔1s输出"hello,world"
      	for i:=1;i<=10 ; i++ {
      		fmt.Println("main() hello world", strconv.Itoa(i))
      		time.Sleep(time.Second)
      	}
      	//查询golang运行的cpu数
      	fmt.Println(runtime.NumCPU()) //4
      	//设置Golang运行的cpu数
      	//runtime.GOMAXPROCS(runtime.NumCPU()-1)	//3
      }
      func test(){
      	for i:=1;i<=10 ; i++ {
      		fmt.Println("test() hello world",strconv.Itoa(i))
      		time.Sleep(time.Second)
      	}
      }
      

      效果图

      Go语言Goroutinue和管道效率详解

      执行流程图

      Go语言Goroutinue和管道效率详解

      goroutinue的调度模型

      MPG

      Go语言Goroutinue和管道效率详解

      MPG运行状态1

      Go语言Goroutinue和管道效率详解

      MPG运行状态2

      Go语言Goroutinue和管道效率详解

      管道(channel)

      不同协程之间如何通讯

      • 全局变量加锁同步
      • channel

      使用全局变量加锁同步改进程序

      • 因为没有对全局变量加锁,因此会出现资源夺取问题,代码会出现错误,提示concurrent map writes
      • 加入互斥锁

      全局变量加锁同步缺陷

      • 主线程在等待所有goroutine全部完成的时间很难确定
      • 如果主线程休眠时间长了,会加长等待时间,如果等待时间短了,可能还有goroutine处于工作状态,这时也会随着主线程的结束而结束
      • 不利于多个协程对全局变量的读写操作

      管道基本介绍

      • 管道本质介绍一个数据结构-队列
      • 数据是先进先出
      • 线程安全,无需加锁
      • 管道有类型

      管道基本使用 声明和定义

      Go语言Goroutinue和管道效率详解

      管道关闭和遍历

      关闭

      使用内置函数close可以关闭channel,关闭后,就不能写入数据,但可读

      遍历

      • 在使用for--range遍历时,如果channel没有关闭,则回出现deadlock错误
      • 在使用for--range遍历时,如果channel已经关闭,则会正常遍历数据

      代码

      package main
      import "fmt"
      func main() {
      	//定义管道
      	var intChjavascriptan chan int
      	intChan =make(chan int,3)
      	//写入数据
      	intChan<-10
      	intChan<-20
      	intChan<-30
      	//遍历
      	close(intChan) //关闭管道
      	for value := range intChan {
      		fmt.Printf("%d\t",value) //10	20	30	
      	}
      }
      

      管道注意事项

      -`channel可以声明为只读,或者只写性质

      Go语言Goroutinue和管道效率详解

      • 使用select可以解决从管道取数据的阻塞问题
      • goroutine中使用recover,解决协程中出现panic,导致程序崩溃问题

      综合案例

      Go语言Goroutinue和管道效率详解

      package main
      import "fmt"
      func main() {
      	numChan := make(chan int, 2000)
      	resChan := make(chan int, 2000)
      	exitChan := make(chan bool, 8)
      	go putNum(numChanphp) //编程客栈存放数据
      	//开启八个协程
      	for i := 0; i < 8; i++ {
      		go add(numChan, resChan, exitChan)
      	}
      	go func() {
      		for i:=0;i<8 ;i++  {
      			<-exitChan
      		}
      		close(resChan)
      	}()
      	for i := 1; i <=2000 ; i++ {
      		fmt.Printf("resChan[%d]=%d\n", i, <-resChan)
      	}
      }
      func putNum(numChan chan int) {
      	for i := 1; i <= 2000; i++ {
      		numChan <- i
      	}
      	close(numChan)
      }
      func add(numChan chan int, resChan chan int, exitChan chan bool) {
      	for {
      		n,ok := <-numChan
      		if !ok{
      			break
      		}
      		res := 0
      		for i := 1; i <= n; i++ {
      			res += i
      		}
      		resChan <- res
      	}
      	exitCha开发者_JAVA入门n<-true
      }
      

      Go语言Goroutinue和管道效率详解

      以上就是Go语言Goroutinue和管道效率详解的详细内容,更多关于Go Goroutinue 管道效率的资料请关注我们其它相关文章!

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜