zoukankan      html  css  js  c++  java
  • 二一:GO语言的goroutine(协程)和channel(管道),重点!!!

    前言:要了解协程和管道首先得了解以下四个概念

      进程和线程简单说明

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

      2.线程是进程的一个执行实例,是程序执行的最小单元,它是比进程更小的独立运行的基本单位

      3.一个进程可以创建销毁多个线程,同一个进程的多个线程可以并发执行

      4.一个程序至少有一个进程,一个进程至少有一个线程

    个人理解:把计算机比作一家公司,程序就是这家公司的部门,进程就是公司安排的某个工作内容的完成过程,线程就是部门里处理这个工作内容的人去完成的实例,公司下发工作内容就相当于给部门下发任务,由公司(这里公司就是只CPU,后面会跟并发和并行有关联)来调动相应的人数去处理这个或者这些任务,如有错误请指出,谢谢。

      并发和并行

      1.多线程程序在单核上运行,就是并发

      2.多线程程序在多核上运行,就是并行

    个人理解:沿用上一个例子,并发就是有多个任务安排,但是现在部门内部只有一个人,这个人就得同时处理所有工作内容,感觉上是所有的任务都在同时处理,但实际上在一个时间点上,这个人只能处理一个问题,只是在不停地切换不同的任务处理,而非处理完成一个任务后再切换到下一个任务。并行就是部门内部有多个人,可以同时处理多个任务

      

    GO的协程和主线程

      1.GO主线程(有程序员直接称为线程/也可以理解成进程),一个GO线程上,可以起多个协程,可以这样理解,协程是轻量级的线程(编译器做优化)。

      2.GO协程的特点

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

    goroutine 快速入门小结

      1.主线程是一个物理线程吗,直接作用在cpu上的,是重量级的,非常消耗cpu资源。

      2.协程从主线程开启的,是轻量级的线程,是逻辑态的。对资源消耗相对小。

      3.Golang的协程机制是重要的特点,可以轻松的开启上万个协程。其他编程语言的并发机制是一般基于线程的,开启过多的线程,资源消耗大,这就突显了Golang在并发上的优势

    goroutine的调度模型(MPG模式)

      基本介绍

      M:操作系统的主线程(是物理线程)

      P:协程执行需要的上下文

      G:协程

    简单来说,就是一个协程阻塞了,会把后续操作自动放到其余空闲的协程中执行,等到阻塞协程完成后,会把剩余的任务又使用该线程继续执行。这样来回切换可以保证阻塞的协程不会影响效率。达成并发/并行的效果

    内容较多,需详细了解请自行搜索查询。

    Channel(管道)

      在协程中进行相互通信时(都要使用同一个全局变量)会产生资源竞争(同时对某一个全局变量进行读写)的问题。

      channel用于解决不同的goroutine之间通信的问题,也可以使用加互斥锁的方式来达成这个目的。但互斥锁没这玩意儿好。

      基本介绍

        1.channel本质就是一个数据结构-队列

        2.数据是先进先出,与栈是相反的,栈是先进后出

        3.线程安全,多个goroutine访问时,不需要加锁,本身就是线程安全的

        4.channel是有类型的,一个string的channel只能存放string类型的数据

      定义/声明

        var 变量名 chan 数据类型

      举例:

        var intChan chan int

        var stringChan chan string

        var structChan chan Struct (结构体)

        var mapChan chan map[string]int (map)

      channel是一个引用类型,必须初始化才能写入数据,即使用make进行初始化,第二个参数为channel的长度

      int类型的管道只能存放int类型的数据

      

      给管道写入数据,拿上面的intChan举例

        

       读取管道中的数据

        

      channel的遍历

        channel支持for-range的方式进行遍历,但注意两个细节

          1.在遍历时,如果chanel没有关闭,则会出现deadlock的错误

          2.在遍历时,如果channel已经关闭,则会正常遍历数据,遍历完后,就会退出遍历

    channel和goroutine使用的注意事项

        1.channel总只能存放指定的数据类型

        2.channel的数据放满后就不能再放入

        3.如果从channel取出数据后,可以继续放入

        4.在没有使用协程的情况下,如果channel的数据取完了,再取就会报dead lock,channel在取值时,实际上会返回两个值,x,ok:=<-chan,第二个值为ok,在成功取出,为false则失败

        5.使用内置函数close可以关闭channel,当channel关闭后,就不能再向channel写数据了,但是仍然可以从该channel读取数据。

        6.在默认情况下,channel管道是双向的,即可度又可写

          var chan2 chan <- int   //只可写入的int型管道

          var chan2 <-chan int    //只可读取的int型管道

        7.使用select可以解决从channel管道中读取数据的阻塞问题

        8.groutine中使用recover,解决协程中出现的panic,防止程序出现崩溃

      

      

  • 相关阅读:
    位运算符的含义与使用
    第三次作业
    软件工程作业二
    大学对于专业的规划
    简要概述java内存模型,以及volatile关键字
    Spring详细教程
    java线程中yield(),sleep(),wait()区别详解
    利用kubeadm快速搭建Kubernetes学习环境
    vue 使用el-time-picker,把数组拆分成单个属性
    Vue+docxtemplater导出到word(包含批量转出图片)!!!
  • 原文地址:https://www.cnblogs.com/WORDPAD/p/15178152.html
Copyright © 2011-2022 走看看